排除匹配字符串的最佳方法?

问题描述 投票:0回答:2

我有一个 MySQL 8 表,约有 40m 行。 我经常运行,尤其是在调试时,一个查询必须从该表中排除几个“名称”,然后按其分组,因此我在

NOT LIKE
子句中使用
WHERE
。这是最高效/最明智的做法还是有更好的做法?

在此示例中,相关列为

QNAME
,请输入
varchar(48)

查询并不是超级慢,但是当添加此过滤器时,您可以清楚地看到 60-90 秒的时间增加,因为当然我相信这是非常低效的。

SELECT 
    ... 
FROM 
    ...
WHERE
    DATE_FORMAT(CREATIONDTE, '%Y-%m-%d') = DATE_FORMAT(CURDATE(), '%Y-%m-%d')
    AND NOT (QNAME LIKE '%IR360%' OR QNAME LIKE '%DEAD%' OR QNAME LIKE 'SYSTEM%' OR QNAME LIKE '%.BO')
GROUP BY 
    QNAME
mysql
2个回答
1
投票

如果您还没有 CREATIONDTE 索引,并且您选择的日期仅代表整个表的一小部分,那么 CREATIONDTE 上的索引可能会提高此特定查询的性能。

你说 LIKE 增加了执行时间,但不是从什么开始的。您也没有给出这些约束排除的表或结果集的比例的估计。如果 LIKE 的计算显着减慢了速度,也许您可以在返回 GROUPed BY 结果后尝试应用 LIKE。例如

SELECT * FROM (
  SELECT QNAME, COUNT(*)
  FROM QNAMES
  GROUP BY QNAME
) A
WHERE A.QNAME NOT LIKE '%XYZ';

0
投票

“CREATIONDTE 上的索引”不会有帮助,因为表达式不是 sargable .

但是,通过改变

DATE_FORMAT(CREATIONDTE, '%Y-%m-%d') = DATE_FORMAT(CURDATE(), '%Y-%m-%d')

CREATIONDTE = CURDATE()  -- if CREATIONDTE is a DATE
CREATIONDTE >= CURDATE()  -- if it is a DATETIME
CREATIONDTE >= CURDATE() AND CREATIONDTE < CURDATE + INTERVAL + 1

然后表达式就变得可控制了,这会有点用。

INDEX(CREATIONDTE)
      

有希望改善

LIKEs

© www.soinside.com 2019 - 2024. All rights reserved.