성능 현명한 문자열 일치
-
18-09-2019 - |
문제
SQL 쿼리가 발행 될 때마다 다음 점검을 실행하는 일반적인 DB 쿼리 기능이 있습니다.
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))
나는 단순한 것을 안다 strpos()
전화는 a보다 훨씬 빠릅니다 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
나는 더 빠른 것처럼 보이기 때문에 다음과 같은 regexes와 함께 갔다.
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)
다른 팁
아마 그 중 어느 것도 사용하지 않을 것입니다. 벤치마킹 없이는 확신 할 수 없지만 substr()
보다 빠른 옵션이 될 것입니다 stripos
, 전체 문자열을 스캔하지 않기 때문에. 가정합니다 UPDATE
그리고 DELETE
항상 쿼리가 시작될 때 항상 발생하고 더 나은 것은 정확히 6 자 길이 가므로 단일로 할 수 있습니다. substr()
:
$queryPrefix = strtoupper(substr($query,0,6));
if ($queryPrefix == 'UPDATE' || $queryPrefix == 'DELETE') {
필요한 경우 추가 할 수 있습니다 trim()
접두사가있는 공백을 위해서는 거기에 있지만 아마도 필요하지 않을 것입니다.
업데이트 및 삭제로 중첩 또는 하위 쿼리를하고 있다면 위의 방법이 작동하지 않을 것이며 stripos()
노선. 정상적인 문자열 함수를 선호하는 정규식을 피할 수 있다면 더 빠르고 덜 복잡합니다.