Performans açısından Dize Eşleştirme

2 Cevap php

Ben aşağıdaki kontrolleri bir SQL sorgusu verilen her zaman çalışan bir genel DB sorgulama fonksiyonunu ettik:

  1. if (preg_match('~^(?:UPDATE|DELETE)~i', $query) === 1)
  2. if (preg_match('~^(?:UPDATE|DELETE)~iS', $query) === 1)
  3. if ((stripos($query, 'UPDATE') === 0) || (stripos($query, 'DELETE') === 0))

Ben strIpos() iki kez Ben gerçekten arıyorum, ancak bu yana, basit bir strpos() çağrısı bir preg_match() yaparak daha hızlı şekilde olduğunu biliyoruz emin olduğum tek iyi performans hangi.

İkinci seçeneği S desen değiştirici ayrıca manuel, kafamda bazı karışıklık getiriyor:

When a pattern is going to be used several times, it is worth spending more time analyzing it in order to speed up the time taken for matching. If this modifier is set, then this extra analysis is performed. At present, studying a pattern is useful only for non-anchored patterns that do not have a single fixed starting character.

Bu durumda hız önemli değildir (aksi takdirde bu genel sorgulama fonksiyonunu kullanarak olmaz) ama, ben yine de basitlik korurken mümkün olduğunca hızlı koşmak yapmak istiyorum.

Which of the above options should I choose?


EDIT: Ben run a simple benchmark ve hala ben yöntem daha iyi çalışır karar veremez.

İşte 10,000 tries için sonuçlar (toplam süresi saniye içinde alınan) şunlardır:

Array
(
    [match] => Array
        (
            [stripos] => 0.0965
            [preg_match] => 0.2445
            [preg_match?] => 0.1227
            [preg_match?S] => 0.0863
        )

    [no-match] => Array
        (
            [stripos] => 0.1165
            [preg_match] => 0.0812
            [preg_match?] => 0.0809
            [preg_match?S] => 0.0829
        )
)

100,000 tries:

Array
(
    [match] => Array
        (
            [stripos] => 1.2049
            [preg_match] => 1.5079
            [preg_match?] => 1.5564
            [preg_match?S] => 1.5857
        )

    [no-match] => Array
        (
            [stripos] => 1.4833
            [preg_match] => 0.8853
            [preg_match?] => 0.8645
            [preg_match?S] => 0.8986
        )
)

1,000,000 tries:

Array
(
    [match] => Array
        (
            [stripos] => 9.4555
            [preg_match] => 8.7634
            [preg_match?] => 9.0834
            [preg_match?S] => 9.1629
        )

    [no-match] => Array
        (
            [stripos] => 13.4344
            [preg_match] => 9.6041
            [preg_match?] => 10.5849
            [preg_match?S] => 8.8814
        )
)

10,000,000 tries:

Array
(
    [match] => Array
        (
            [stripos] => 86.3218
            [preg_match] => 93.6755
            [preg_match?] => 92.0910
            [preg_match?S] => 105.4128
        )

    [no-match] => Array
        (
            [stripos] => 150.9792
            [preg_match] => 111.2088
            [preg_match?] => 100.7903
            [preg_match?S] => 88.1984
        )
)

Eğer sonuç bir çok değişebilir görebileceğiniz gibi, bu bir kriter yapmak için doğru yolu ise beni meraklandırıyor.

2 Cevap

Onlar (eşleştirilmiş ve non-eşleşen metin üzerinde) daha hızlı gibi görünüyor çünkü ben şu regexes ile gitti:

  1. if (preg_match('~^(?:INSERT|REPLACE)~i', $query) === 1)
  2. else if (preg_match('~^(?:UPDATE|DELETE)~i', $query) === 1)
  3. else if (preg_match('~^(?:SELECT|EXPLAIN)~i', $query) === 1)

Herhalde bu herhangi kullanmak olmaz. Ben kıyaslama olmadan emin olamam, ama bütün dize tarama olmaz gibi ben, bir substr() stripos daha hızlı bir seçenek olacağını düşünüyorum. UPDATE ve DELETE Her zaman bir sorgunun başında meydana varsayarsak, ve tek bir {[(0 bunu böylece daha iyi, ikisi tam 6 karakter uzunluğunda konum )]}:

$queryPrefix = strtoupper(substr($query,0,6));
if ($queryPrefix == 'UPDATE' || $queryPrefix == 'DELETE') {

Eğer gerekirse, herhangi bir boşluk karakteri önekli için orada bir trim() ekleyebilirsiniz, ancak muhtemelen gerekli değildir.

Eğer update ile iç içe veya alt sorguları yapıyor ve DELETE ediyorsanız, o zaman tabii ki yukarıdaki yöntem işe yaramaz, ve ben stripos() rota ile gitmek istiyorum. Normal string fonksiyonları lehine düzenli ifadeler önleyebilirsiniz, daha hızlı ve daha az karmaşık olacaktır.