Performance weise String Matching
-
18-09-2019 - |
Frage
Ich habe eine generische Abfrage-Funktion DB, das jedes Mal, wenn eine SQL-Abfrage der folgenden Prüfungen ausgeführt wird ausgegeben:
-
if (preg_match('~^(?:UPDATE|DELETE)~i', $query) === 1)
-
if (preg_match('~^(?:UPDATE|DELETE)~iS', $query) === 1)
-
if ((stripos($query, 'UPDATE') === 0) || (stripos($query, 'DELETE') === 0))
Ich weiß, dass ein einfacher strpos()
Anruf ist viel schneller als ein preg_match()
tun, aber da ich rufe strIpos()
zweimal Ich bin wirklich nicht sicher, welche sollte man besser.
Das S
Muster Modifikator in der zweiten Option bringt auch einige Verwirrung in meinem Kopf, aus dem Handbuch:
Wenn ein Muster verwendet werden soll mehrmals, ist es wert, es mehr Zeit, um die Analyse zu beschleunigt die Zeit für die Übereinstimmungen aufgenommen. Wenn dieser Modifikator gesetzt ist, dann ist diese zusätzliche Analyse durchgeführt wird. Beim Derzeit ein Muster zu studieren ist nützlich nur für nicht-verankerte Muster, die tun nicht einen einzigen festen Start haben Charakter.
In dieser Fall Geschwindigkeit nicht kritisch ist (sonst würde ich nicht diese allgemeine Abfrage-Funktion verwenden), aber ich würde immer noch gerne es so schnell wie möglich machen läuft unter Beibehaltung seiner Einfachheit.
Welche der oben genannten Optionen soll ich wählen?
EDIT: Ich habe eine einfache Benchmark laufen und immer noch ich nicht entscheiden kann, welche Methode besser funktioniert.
Hier sind die Ergebnisse für 10.000 Versuche (Gesamtzeit, in Sekunden):
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 versucht :
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 versucht :
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 versucht :
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
)
)
Wie Sie die Ergebnisse sind sehr unterschiedlich sehen können, das macht mich frage mich, ob dies der richtige Weg ist, einen Maßstab zu tun.
Lösung 2
Ich ging mit dem folgenden regulären Ausdrücke, da sie scheinen schneller zu sein (auf abgestimmt und nicht-angepassten Text):
-
if (preg_match('~^(?:INSERT|REPLACE)~i', $query) === 1)
-
else if (preg_match('~^(?:UPDATE|DELETE)~i', $query) === 1)
-
else if (preg_match('~^(?:SELECT|EXPLAIN)~i', $query) === 1)
Andere Tipps
Ich würde wahrscheinlich nicht irgendwelche von denen verwenden. Ich kann ohne Benchmarking nicht sicher sein, aber ich denke, ein substr()
eine schnellere Option als stripos
wäre, da wäre es nicht die gesamte Zeichenfolge scannen. Unter der Annahme, UPDATE
und DELETE
tritt immer am Anfang einer Abfrage, und noch besser, sie sind beide genau 6 Zeichen lang, so dass Sie es in einem einzigen substr()
tun könnten:
$queryPrefix = strtoupper(substr($query,0,6));
if ($queryPrefix == 'UPDATE' || $queryPrefix == 'DELETE') {
Wenn Sie benötigt, können es für jeden vorangestelltes Leerzeichen ein trim()
hinzufügen könnte, aber es ist wahrscheinlich nicht erforderlich.
Wenn Sie verschachtelt tut oder Unterabfragen mit UPDATE und DELETE, dann natürlich das obige Verfahren nicht funktionieren würde, und ich würde mit dem stripos()
Weg gehen. Wenn Sie reguläre Ausdrücke für normale String-Funktionen vermeiden können, wird es schneller und weniger kompliziert.