我有一个 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
如果您还没有 CREATIONDTE 索引,并且您选择的日期仅代表整个表的一小部分,那么 CREATIONDTE 上的索引可能会提高此特定查询的性能。
你说 LIKE 增加了执行时间,但不是从什么开始的。您也没有给出这些约束排除的表或结果集的比例的估计。如果 LIKE 的计算显着减慢了速度,也许您可以在返回 GROUPed BY 结果后尝试应用 LIKE。例如
SELECT * FROM (
SELECT QNAME, COUNT(*)
FROM QNAMES
GROUP BY QNAME
) A
WHERE A.QNAME NOT LIKE '%XYZ';
“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
。