4

SQLクエリが発行されるたびに次のチェックを実行する汎用DBクエリ関数があります。

  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))

strpos()単純な呼び出しは、を実行するよりもはるかに高速であることを私は知っていますが、 2回preg_match()呼び出しているので、どちらがより良いパフォーマンスを発揮するかは本当にわかりません。strIpos()

2番目のオプションのSパターン修飾子も、マニュアルから、私の頭にいくつかの混乱をもたらします。

パターンを複数回使用する場合は、マッチングにかかる​​時間を短縮するために、パターンの分析に時間をかける価値があります。この修飾子が設定されている場合、この追加の分析が実行されます。現在、パターンの調査は、開始文字が1つ固定されていないアンカーされていないパターンにのみ役立ちます。

この場合、速度は重要ではありませんが(そうでない場合は、この汎用クエリ関数を使用しません)、単純さを維持しながら、可能な限り高速に実行したいと思います。

上記のオプションのどれを選択する必要がありますか?


編集:私は単純なベンチマークを実行しましたが、それでもどちらの方法がより効果的かを判断できません。

10,000回の試行の結果は次のとおりです(合計所要時間、秒単位)。

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回の試行

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回の試行

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回の試行

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
        )
)

結果は大きく異なることがわかるように、これがベンチマークを実行する正しい方法であるかどうか疑問に思います。

4

2 に答える 2

2

私はおそらくそれらのどれも使用しないでしょう。ベンチマークなしでは確信が持てませんが、文字列全体をスキャンしないため、substr()aよりも高速なオプションだと思います。striposクエリの開始時に常に発生すると仮定するUPDATEDELETE、さらに良いことに、両方とも正確に6文字の長さであるため、1回で実行できますsubstr()

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

必要に応じて、trim()接頭辞付きの空白を追加することもできますが、おそらく必要ありません。

UPDATEとDELETEを使用してネストされたクエリまたはサブクエリを実行している場合は、明らかに上記の方法は機能しないので、stripos()ルートを使用します。通常の文字列関数を優先して正規表現を回避できれば、より高速で複雑さが軽減されます。

于 2010-01-06T04:08:19.317 に答える
0

次の正規表現を使用したのは、(一致するテキストと一致しないテキストで)高速であるように見えるためです。

  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)
于 2010-01-08T03:16:44.323 に答える