Question

J'ai une fonction générique de requête DB qui exécute les contrôles suivants à chaque fois qu'une requête SQL est émise:

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

Je sais qu'un simple appel strpos() est beaucoup plus rapide que de faire un preg_match(), mais depuis que je vous appelle strIpos() deux fois Je ne suis pas sûr que l'on devrait mieux performer.

Le modificateur de motif S dans la deuxième option apporte également une certaine confusion dans ma tête, du manuel:

  

Quand un motif va être utilisé   plusieurs fois, il vaut la peine de dépenser   plus de temps à l'analyser afin de   accélérer le temps pour la correspondance.   Si ce modificateur est défini, ce   analyse supplémentaire est effectuée. À   présent, l'étude d'un modèle est utile   seulement pour des motifs non ancrés qui font   pas un seul départ fixe   caractère.

Dans ce cas, la vitesse de n'est pas critique (sinon je ne serais pas en utilisant cette fonction de requête générique), mais je voudrais encore faire courir aussi vite que possible tout en maintenant sa simplicité.

Laquelle des options ci-dessus dois-je choisir?


EDIT: J'ai exécuter un simple indice de référence et encore je ne peut pas décider quelle méthode fonctionne mieux.

Voici les résultats pour 10.000 essais (durée totale, en secondes):

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 essais :

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 tente :

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 tente :

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

Comme vous pouvez le voir les résultats varient beaucoup, cela me demande si c'est la bonne façon de faire une référence.

Était-ce utile?

La solution 2

Je suis allé avec les regexes suivants car ils semblent être plus rapide (sur correspondance et texte non adapté):

  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)

Autres conseils

Je ne serais probablement pas utiliser l'un de ces. Je ne peux pas être sûr sans l'analyse comparative, mais je pense que substr() serait une option plus rapide que stripos, car il ne scanne pas toute la chaîne. En supposant UPDATE et DELETE se produisent toujours au début d'une requête, et mieux encore, ils sont tous les deux exactement 6 caractères, de sorte que vous pouvez le faire en une seule substr():

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

Si vous avez besoin, vous pourriez ajouter un trim() là-bas pour les espaces blancs préfixée, mais il est probablement pas nécessaire.

Si vous faites imbriquées ou sous-requêtes avec UPDATE et DELETE, il est évident que la méthode ci-dessus ne fonctionnerait pas, et je partirais avec la route stripos(). Si vous pouvez éviter des expressions régulières en faveur des fonctions normales de chaînes, il sera plus rapide et moins compliqué.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top