Производительность мудрое соответствие строк - PullRequest
4 голосов
/ 06 января 2010

У меня есть общая функция запроса к БД, которая запускает следующие проверки каждый раз при выполнении запроса 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))

Я знаю, что простой strpos() вызов намного быстрее, чем preg_match(), однако, поскольку я звоню strIpos() дважды , я действительно не уверен, какой из них должен работать лучше.

Модификатор S во втором варианте также вносит некоторую путаницу в мою голову из руководства:

Когда будет использоваться шаблон стоит потратить несколько раз больше времени на его анализ, чтобы ускорить время, необходимое для сопоставления. Если этот модификатор установлен, то этот проводится дополнительный анализ. В настоящее, изучение шаблона полезно только для не закрепленных шаблонов, которые делают не имеют ни одного фиксированного пуска характер.

В этом случае скорость не критична (в противном случае я бы не использовал эту универсальную функцию запроса), но я все же хотел бы, чтобы она работала как можно быстрее при сохранении ее простоты.

Какой из вышеперечисленных вариантов мне выбрать?


РЕДАКТИРОВАТЬ: Я запустить простой тест , и все же я не могу решить, какой метод работает лучше.

Вот результаты для 10 000 попыток (общее время, занятое в секундах):

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 попыток :

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 попыток :

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 попыток :

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

Как вы можете видеть, результаты сильно различаются, поэтому я задаюсь вопросом, является ли это правильным способом сделать тест.

Ответы [ 2 ]

2 голосов
/ 06 января 2010

Я бы, наверное, не использовал ни одного из них. Я не могу быть уверен без бенчмаркинга, но я думаю, что substr() будет более быстрым вариантом, чем stripos, так как он не будет сканировать всю строку. Предполагая, что UPDATE и DELETE всегда появляются в начале запроса, и, что еще лучше, оба они имеют длину ровно 6 символов, так что вы можете сделать это за один substr():

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

Если вам нужно, вы можете добавить туда trim() для любого префиксного пробела, но, вероятно, в этом нет необходимости.

Если вы выполняете вложенные или подзапросы с UPDATE и DELETE, то, очевидно, вышеописанный метод не сработает, и я бы пошел по маршруту stripos(). Если вы можете избежать регулярных выражений в пользу обычных строковых функций, это будет быстрее и менее сложным.

0 голосов
/ 08 января 2010

Я использовал следующие регулярные выражения, так как они кажутся быстрее (для сопоставленного и несоответствующего текста):

  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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...