Desempenho strings sábio
-
18-09-2019 - |
Pergunta
Eu tenho uma função de consulta DB genérico que executa as seguintes verificações cada vez uma consulta SQL é emitido:
-
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))
Eu sei que uma chamada strpos()
simples é muito mais rápido do que fazer uma preg_match()
, no entanto desde que eu estou chamando strIpos()
duas vezes Eu realmente não estou certo de que se deve ter um melhor desempenho.
O modificador padrão S
na segunda opção também traz alguma confusão na minha cabeça, a partir do manual:
Quando um padrão que vai ser usado várias vezes, vale a pena gastar mais tempo analisando-o, a fim de acelerar o tempo necessário para correspondência. Se este modificador é definido, então este análise adicional é executada. em Presentemente, o estudo de um padrão é útil apenas para os padrões não-ancorada que fazer não ter um único fixo de partida caráter.
Neste velocidade caso não é crítica (caso contrário eu não estaria usando esta função consulta genérico), mas eu ainda gostaria de torná-lo correr tão rápido quanto possível, mantendo a sua simplicidade.
Qual das opções acima devo escolher?
EDIT: Não tenho executar um referência simples e ainda assim eu não pode decidir qual método funciona melhor.
Aqui estão os resultados para 10.000 tentativas (tempo total, em segundos):
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 tentativas :
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 tentativas :
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 tentativas :
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
)
)
Como você pode ver os resultados variam muito, isso me faz pensar se esta é a maneira correta de fazer um ponto de referência.
Solução 2
Eu fui com as seguintes expressões regulares desde que parecem ser mais rápido (no combinado e não combinado texto):
-
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)
Outras dicas
Eu provavelmente não usar qualquer um desses. Eu não posso ter certeza sem aferição, mas acho que um substr()
seria uma opção mais rápido do que stripos
, uma vez que não verificar toda a string. Assumindo UPDATE
e DELETE
sempre ocorrem no início de uma consulta, e ainda melhor, ambos são exatamente 6 caracteres, de modo que você poderia fazê-lo em um único substr()
:
$queryPrefix = strtoupper(substr($query,0,6));
if ($queryPrefix == 'UPDATE' || $queryPrefix == 'DELETE') {
Se você precisava, você pode adicionar um trim()
lá para qualquer espaço em branco prefixado, mas provavelmente não é necessário.
Se você está fazendo aninhados ou sub-consultas com UPDATE e DELETE, então, obviamente, o método acima não iria funcionar, e eu iria com a rota stripos()
. Se você pode evitar expressões regulares em favor das funções normais de cordas, será mais rápido e menos complicado.