Details
-
Bug
-
Status: Open (View Workflow)
-
Major
-
Resolution: Unresolved
-
10.11, 11.4, 11.8, 12.3, 13.0, 13.1, 13.2
Description
# REGEXP_REPLACE on 300000 characters, each one a match |
SET @t= UNIX_TIMESTAMP(NOW(6)); |
SELECT LENGTH(REGEXP_REPLACE(REPEAT('a', 300000), 'a', 'b')) INTO @l; |
--let $s= query_get_value(SELECT ROUND(UNIX_TIMESTAMP(NOW(6)) - @t) AS s, s, 1)
|
if ($s > 10) |
{
|
--die REGEXP_REPLACE on 300000 characters ran for $s seconds |
}
|
Leads to:
|
CS 13.1.2 87e62ca17270e163a6d41b3fc8d6f4d440f1bb88 (Optimized, Clang 22.1.8-20260622) Build 05/10/2026 |
mysqltest: At line 7: REGEXP_REPLACE on 300000 characters ran for 43 seconds
|
|
CS 13.1.0 da18481158c81ca94689702073c3e04aad85a6a3 (Debug, Clang 22.1.8-20260622) Build 18/08/2026 |
mysqltest: At line 7: REGEXP_REPLACE on 300000 characters ran for 111 seconds
|
The time grows with the square of the string length. SELECT LENGTH(REGEXP_REPLACE(s, 'a', 'b')) in the client, where s is REPEAT('a', n) in the given character set:
|
CS 13.1.2 87e62ca17270e163a6d41b3fc8d6f4d440f1bb88 (Optimized, Clang 22.1.8-20260622) Build 05/10/2026 |
n utf8mb4 latin1 binary
|
50000 1.08 s 0.87 s 0.05 s
|
100000 4.93 s 5.10 s 0.05 s
|
200000 21.52 s 20.02 s 0.06 s
|
600000 160.51 s
|
Three gdb samples of the query thread all show the UTF-8 check of PCRE2, each time over a large part of the subject:
|
CS 13.1.2 87e62ca17270e163a6d41b3fc8d6f4d440f1bb88 (Optimized, Clang 22.1.8-20260622) Build 05/10/2026 |
#0 _pcre2_valid_utf_8 (string=0x6e5f201304c3 'a' <repeats 200 times>..., length=375545, erroroffset=0x6e5f200165d0) at extra/pcre2/src/pcre2/src/pcre2_valid_utf.c:133
|
#1 0x00005c2f22ba72c3 in pcre2_match_8 (code=<optimized out>, subject=0x6e5f20104c20 'a' <repeats 200 times>..., length=600000, start_offset=<optimized out>, options=<optimized out>, match_data=0x6e5f20016570, mcontext=0x0) at extra/pcre2/src/pcre2/src/pcre2_match.c:7337
|
#2 0x00005c2f22a4251d in Regexp_processor_pcre::pcre_exec_with_warn (this=0x6e5f20018770, code=0x6e5f201304c3, data=0x6e5f20016570, subject=0x5baf9 <error: Cannot access memory at address 0x5baf9>, length=<optimized out>, startoffset=<optimized out>, options=0) at sql/item_cmpfunc.cc:6390
|
#3 Regexp_processor_pcre::exec (this=this@entry=0x6e5f20018770, str=0x5baf9 <error: Cannot access memory at address 0x5baf9>, str@entry=0x6e5f20104c20 'a' <repeats 200 times>..., length=length@entry=600000, offset=offset@entry=178339) at sql/item_cmpfunc.cc:6407
|
#4 0x00005c2f22aa05f1 in Item_func_regexp_replace::val_str_internal (this=0x6e5f200186b0, str=0x6e5f200189e0, null_to_empty=<optimized out>) at sql/item_strfunc.cc:1628
|
From the code it seems that Item_func_regexp_replace::val_str_internal() calls Regexp_processor_pcre::exec() once for each match (sql/item_strfunc.cc:1628), and that exec() calls pcre2_match() with options 0 (sql/item_cmpfunc.cc:6390 and sql/item_cmpfunc.cc:6407). So each call checks the rest of the subject for valid UTF-8 again. A binary subject has no UTF-8 check, which matches the binary column above. The PCRE2 documentation suggests PCRE2_NO_UTF_CHECK for the second and subsequent calls to pcre2_match() on the same subject.
Attachments
Issue Links
- relates to
-
MDEV-12403 REGEXP: performance can be very very poor
-
- Closed
-