Domanda

Ho un funzione di query DB generica che esegue i seguenti controlli ogni volta che viene rilasciata una query SQL:

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

So che una semplice chiamata strpos() è il modo più veloce di fare un preg_match(), tuttavia, poiché sto chiamando strIpos() due volte non sono davvero sicuro che si dovrebbe svolgere meglio.

Il modificatore modello S nella seconda opzione porta anche un po 'di confusione in testa, dal manuale:

  

Quando un modello sta per essere usato   più volte, vale la pena spendere   più tempo ad analizzare al fine di   accelerare il tempo impiegato per la corrispondenza.   Se questo modificatore è impostato, allora questo   analisi in più viene eseguita. A   Attualmente, studiando un modello è utile   solo per motivi non ancorato che fanno   non hanno una sola partenza fissa   carattere.

In questo caso la velocità non è critico (altrimenti non sarebbe utilizzando questa funzione query standard) ma, ancora desidero farlo funzionare più velocemente possibile, pur mantenendo la sua semplicità.

Quale delle opzioni di cui sopra devo scegliere?


Modifica eseguire un punto di riferimento semplice ed ancora io non può decidere quale metodo funziona meglio.

Ecco i risultati per 10.000 tentativi (tempo totale impiegato, in secondi):

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

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

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

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

Come si può vedere i risultati variano molto, questo mi domando se questo è il modo corretto di fare un punto di riferimento.

È stato utile?

Soluzione 2

Sono andato con i seguenti regex poiché sembrano essere più veloce (in abbinata e non abbinati testo):

  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)

Altri suggerimenti

Probabilmente non utilizzare una di queste. Non posso essere sicuro, senza l'analisi comparativa, ma penso che un substr() sarebbe una scelta più veloce di stripos, in quanto non eseguire la scansione l'intera stringa. Supponendo UPDATE e DELETE avvengono sempre all'inizio di una query, e anche meglio, sono entrambi esattamente 6 caratteri, in modo che si possa fare in un unico substr():

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

Se hai bisogno di, si potrebbe aggiungere un trim() in là per qualsiasi spazio bianco prefissato, ma probabilmente non è necessario.

Se stai facendo nidificati o sub-query con UPDATE e DELETE, poi, ovviamente, il metodo di cui sopra potrebbe non funzionare, e mi piacerebbe andare con il percorso stripos(). Se si può evitare espressioni regolari a favore delle normali funzioni di stringa, sarà più veloce e meno complicato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top