如何提高MySQL中REGEXP字符串匹配的性能?

尤里

前言:

我已经做了很多(重新)搜索,然后找到了以下SO post / answer:https : //stackoverflow.com/a/5361490/6095216,它与我要找的东西非常接近。相同的代码,但有一些更有用的注释,出现在这里:http : //thenoyes.com/littlenoise/?p=136

问题描述:

我需要将MySQL TEXT数据的1列拆分为多列,其中原始数据具有以下格式(N <= 7):

{"field1":"value1","field2":"value2",...,"fieldN":"valueN"}

您可能会猜到,我只需要提取,然后将每个放到单独的(预定义)列中即可。问题在于,不能保证所有记录的字段数量和顺序都相同。因此,使用SUBSTR / LOCATE等的解决方案不起作用,我需要使用正则表达式。另一个限制是,不能使用诸如LIB_MYSQLUDF_PREG之类的第三方库(在上面我的第一条链接的答案中建议)。

到目前为止的解决方案/进度:

我已经修改了上述链接中的代码,以使其返回从左到右的第一个/最短匹配项;否则,返回NULL。我也对其进行了重构,使标识符对阅读器/维护者更友好:)这是我的版本:

CREATE FUNCTION REGEXP_EXTRACT_SHORTEST(string TEXT, exp TEXT)
RETURNS TEXT DETERMINISTIC
BEGIN
    DECLARE adjustStart, adjustEnd BOOLEAN DEFAULT TRUE;
    DECLARE startInd INT DEFAULT 1;
    DECLARE endInd, strLen INT;
    DECLARE candidate TEXT;

    IF string NOT REGEXP exp THEN
        RETURN NULL;
    END IF;

    IF LEFT(exp, 1) = '^' THEN
        SET adjustStart = FALSE;
    ELSE
        SET exp = CONCAT('^', exp);
    END IF;
    IF RIGHT(exp, 1) = '$' THEN
        SET adjustEnd = FALSE;
    ELSE
        SET exp = CONCAT(exp, '$');
    END IF;

    SET strLen = LENGTH(string);
    StartIndLoop: WHILE (startInd <= strLen) DO
        IF adjustEnd THEN
            SET endInd = startInd;
        ELSE
            SET endInd = strLen;
        END IF;
        EndIndLoop: WHILE (endInd <= strLen) DO
            SET candidate = SUBSTRING(string FROM startInd FOR (endInd - startInd + 1));
            IF candidate REGEXP exp THEN
                RETURN candidate;
            END IF;
            IF adjustEnd THEN
                SET endInd = endInd + 1;
            ELSE
                LEAVE EndIndLoop;
            END IF;
        END WHILE EndIndLoop;
        IF adjustStart THEN
            SET startInd = startInd + 1;
        ELSE
            LEAVE StartIndLoop;
        END IF;
    END WHILE StartIndLoop;
    RETURN NULL;
END;

然后,我添加了一个辅助函数,以避免必须重复正则表达式模式,正如您从上面看到的那样,所有字段都是相同的。这是该函数(我放弃了使用回溯的尝试-在MySQL中不受支持-作为注释):

CREATE FUNCTION GET_MY_FLD_VAL(inputStr TEXT, fldName TEXT)
RETURNS TEXT DETERMINISTIC
BEGIN
    DECLARE valPattern TEXT DEFAULT '"[^"]+"'; /* MySQL doesn't support lookaround :( '(?<=^.{1})"[^"]+"'*/
    DECLARE fldNamePat TEXT DEFAULT CONCAT('"', fldName, '":');
    DECLARE discardLen INT UNSIGNED DEFAULT LENGTH(fldNamePat) + 2;
    DECLARE matchResult TEXT DEFAULT REGEXP_EXTRACT_SHORTEST(inputStr, CONCAT(fldNamePat, valPattern));
    RETURN SUBSTRING(matchResult FROM discardLen FOR LENGTH(matchResult) - discardLen);
END;

当前,我要尝试做的就是使用上面的代码进行简单的SELECT查询。它正常工作,但是。是。SLOOOOOOOW ...最多只能拆分7个字段/列(并非所有记录都具有全部7个)!仅限于20条记录,大约需要3分钟-我总共大约有40,000条记录(对于数据库来说不是很多,对吧!!):)

因此,最后,我们得到了一个实际的问题:[如何]在性能上显着改善上述算法/代码(在这一点上几乎是粗暴的搜索),以便可以在实际的数据库中运行该算法/代码。合理的时间?我开始研究已知的主要模式匹配算法,但很快就迷失了方向,试图找出适合的算法,这在很大程度上是由于可用选项的数量及其各自的限制,使用条件等所致。似乎在SQL中实现其中之一只是为了看看是否有帮助,可能需要很多工作。

注意:这是我有史以来的第一篇文章(!),所以如果有不清楚的地方,请(很好地)让我知道,等等,我将尽力解决它。提前致谢。

尤里

正如上面的tadman和Matt Raines所建议的,我能够通过解析JSON来解决这个问题。作为JSON概念的新手,我只是根本不知道可以用这种方式完成它……有点尴尬,但可以吸取教训!

无论如何,我在common_schema框架中使用了get_option函数:https : //code.google.com/archive/p/common-schema/(可通过本文找到,它还演示了如何使用该函数:在MySQL中解析JSON) 。结果,我的INSERT查询运行大约需要15分钟,而使用REGEXP解决方案则需要30多个小时。谢谢,直到下一次!:)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何提高基于字符串的查询联接的性能?

来自分类Dev

提高VBA字符串比较的性能

来自分类Dev

如何使用RegExp在QT中匹配字符后面的字符串?

来自分类Dev

REGEXP使用MySQL匹配字符串中的两个关键字

来自分类Dev

Javascript-RegExp在替换中返回匹配的字符串

来自分类Dev

用R中的regexp替换完全匹配的字符串

来自分类Dev

Python RegExp从匹配的字符串中检索值

来自分类Dev

如何通过Regexp匹配字符串中的bar,bar,b--a--r等

来自分类Dev

无法匹配mysql中的字符串

来自分类Dev

匹配 mysql 列中的字符串

来自分类Dev

如何使用regexp在Oracle中使用匹配字符串拆分字符串?

来自分类Dev

如何使用regexp在Oracle中使用匹配字符串拆分字符串?

来自分类Dev

如何匹配字符串中的日期

来自分类Dev

如何匹配文件中的字符串

来自分类Dev

字符串匹配性能:gcc与CPython

来自分类Dev

Mysql regexp匹配<year>,<year_0>,<year_1>标记中的相同子字符串

来自分类Dev

如何从中间选择 RegExp 中的特定字符串

来自分类Dev

如何从匹配中只获取完全匹配的字符串

来自分类Dev

使用mysql regexp搜索字符串

来自分类Dev

如何匹配字符串中的给定字符

来自分类Dev

Perl:如何匹配字符串中的特定字符?

来自分类Dev

如何替换字符串中匹配的字符?(红宝石)

来自分类Dev

MySQL查询使用REGEXP查找匹配的字符串不起作用

来自分类Dev

mysql REGEXP匹配以2位数字结尾且仅以非数字开头的字符串

来自分类Dev

如何在MySQL中匹配正好有2个斜杠的字符串

来自分类Dev

MySQL正则表达式:如何用\ d匹配字符串中的数字?

来自分类Dev

如何使用mysql php选择与字符串中某些单词匹配的所有记录

来自分类Dev

如何在MySql中的任何字符串匹配后检索数据?

来自分类Dev

regexp只匹配前后无字符的字符串

Related 相关文章

  1. 1

    如何提高基于字符串的查询联接的性能?

  2. 2

    提高VBA字符串比较的性能

  3. 3

    如何使用RegExp在QT中匹配字符后面的字符串?

  4. 4

    REGEXP使用MySQL匹配字符串中的两个关键字

  5. 5

    Javascript-RegExp在替换中返回匹配的字符串

  6. 6

    用R中的regexp替换完全匹配的字符串

  7. 7

    Python RegExp从匹配的字符串中检索值

  8. 8

    如何通过Regexp匹配字符串中的bar,bar,b--a--r等

  9. 9

    无法匹配mysql中的字符串

  10. 10

    匹配 mysql 列中的字符串

  11. 11

    如何使用regexp在Oracle中使用匹配字符串拆分字符串?

  12. 12

    如何使用regexp在Oracle中使用匹配字符串拆分字符串?

  13. 13

    如何匹配字符串中的日期

  14. 14

    如何匹配文件中的字符串

  15. 15

    字符串匹配性能:gcc与CPython

  16. 16

    Mysql regexp匹配<year>,<year_0>,<year_1>标记中的相同子字符串

  17. 17

    如何从中间选择 RegExp 中的特定字符串

  18. 18

    如何从匹配中只获取完全匹配的字符串

  19. 19

    使用mysql regexp搜索字符串

  20. 20

    如何匹配字符串中的给定字符

  21. 21

    Perl:如何匹配字符串中的特定字符?

  22. 22

    如何替换字符串中匹配的字符?(红宝石)

  23. 23

    MySQL查询使用REGEXP查找匹配的字符串不起作用

  24. 24

    mysql REGEXP匹配以2位数字结尾且仅以非数字开头的字符串

  25. 25

    如何在MySQL中匹配正好有2个斜杠的字符串

  26. 26

    MySQL正则表达式:如何用\ d匹配字符串中的数字?

  27. 27

    如何使用mysql php选择与字符串中某些单词匹配的所有记录

  28. 28

    如何在MySql中的任何字符串匹配后检索数据?

  29. 29

    regexp只匹配前后无字符的字符串

热门标签

归档