Pregunta

Tengo una función genérica consulta DB que ejecuta los siguientes controles cada vez que se emite una consulta 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))

Sé que una simple llamada strpos() es mucho más rápido que haciendo un preg_match(), sin embargo, ya que estoy llamando a strIpos() dos veces Realmente no estoy seguro de cuál debería funcionar mejor.

El modificador de patrón S en la segunda opción también trae cierta confusión en la cabeza, en el manual:

  

Cuando un patrón se va a utilizar   varias veces, vale la pena el gasto   más tiempo de analizarlo con el fin de   acelerar el tiempo necesario para la coincidencia.   Si este modificador está establecido, entonces este   Se realizó un análisis adicional. A   presente, el estudio de un patrón es útil   sólo para patrones no anclado que hacen   no tener una sola partida fijo   personaje.

En este caso la velocidad no es crítica (de lo contrario no estaría utilizando esta función de consulta genérica), pero, todavía me gustaría hacer que se ejecute lo más rápido posible, manteniendo su simplicidad.

¿Cuál de las opciones anteriores debería elegir?


EDIT: He ejecutar una referencia sencilla y todavía me no puede decidir qué método funciona mejor.

Aquí son los resultados para 10.000 tries (tiempo total, en 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 intentos

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 intentos

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 intentos

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 se puede ver los resultados varían mucho, esto hace que me pregunte si esta es la forma correcta de hacer un punto de referencia.

¿Fue útil?

Solución 2

Me fui con las siguientes expresiones regulares ya que parecen ser más rápido (en emparejados y no emparejados texto):

  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)

Otros consejos

Lo que probablemente no utilizar cualquiera de ellos. No puedo estar seguro sin evaluación comparativa, pero creo que un substr() sería una opción más rápida que stripos, ya que no sería escanear toda la cadena. Suponiendo UPDATE y DELETE siempre se producen en el inicio de una consulta, y aún mejor, los dos son exactamente 6 caracteres de longitud, por lo que podría hacerlo en una sola substr():

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

Si usted necesitó, se puede añadir un trim() de la existencia de cualquier espacio en blanco prefijado, pero probablemente no es necesario.

Si estás haciendo anidada o sub-consultas con actualizar y eliminar, entonces, evidentemente, el método anterior no funcionaría, y me gustaría ir con la ruta stripos(). Si se puede evitar expresiones regulares en favor de las funciones normales de cadena, que será más rápido y menos complicado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top