mysql-没有正确索引的长时间运行查询

wf82jlnq  于 2021-06-21  发布在  Mysql
关注(0)|答案(2)|浏览(448)

这个查询在生产中运行了大约15个小时,我正在寻找替代方案来改进它,
我认为有些改进可能会有所帮助,请参见以下评论:

SELECT  table1.*
    FROM  table1
    WHERE  UPPER(LEFT(table1.cloumn1, 1)) IN ('A', 'B')
      AND  table1.cloumn2 = 'N' /* add composite index for cloumn2,
        column3 */
      AND  table1.cloumn3 != 'Y'
      AND  table1.id IN (
        SELECT  MAX(id)
            FROM  table1
            GROUP BY  column5,column6
                        ) /* move this clause to 2nd after
    where  */
      AND  table1.column4 IN (
        SELECT  column1
            FROM  table2
            WHERE  column2 IN ('VALUE1', 'VALUE2')
              AND  (SUBSTRING(column3,6,1) = 'Y'
                      OR  SUBSTRING(column3,25,1) = 'Y')
                          ) /* move this clause to 1st after
    where  */
      AND  (table1.column5,table1.column6) NOT IN (
        SELECT  column1, column2
            FROM  table3
            WHERE  table3.column3 IN ('A', 'B')/* add index for this column*/
           )
      AND  DATE_FORMAT(timstampColumn, '%Y/%m/%d') > DATE_ADD(CURRENT_DATE,
                INTERVAL - 28 DAY)) /* need index  ON this col? */ ;

如有任何意见/建议,我们将不胜感激。
更新:只更新过滤顺序,查询性能提高到28秒左右,添加一些索引并替换一些子查询到连接后,将在此处更新

pqwbnv8z

pqwbnv8z1#

假设您可以添加有用的索引(这将有助于您的一些检查),那么可以尝试尽早排除行。
我怀疑表1中每列5/6的组合都有相当多的行。如果您能尽早获得其中每一个的最新信息(即,使用您加入的子查询),那么您就可以在需要检查任何未编入索引的where子句之前从表1中排除大多数行。您还可以通过对表3上的子查询执行进一步的联接来排除其中的一些查询。
没有测试,但如果我对你的数据库结构的假设是正确的,那么这可能是一个即时消息provement:-

SELECT table1.* 
FROM 
(
    SELECT MAX(table1.id) AS max_id
    FROM table1 
    INNER JOIN 
    (
        SELECT DISTINCT column1, column2 
        FROM table3
        WHERE table3.column3 IN ('A', 'B')
        AND DATE_FORMAT(timstampColumn, '%Y/%m/%d') > DATE_ADD(CURRENT_DATE, INTERVAL - 28 DAY)
    ) sub0_0
    ON table1.column5 = sub0_0.column1
    AND  table1.column6 = sub0_0.column2
    WHERE (table1.cloumn1 LIKE 'A%' OR table1.cloumn1 LIKE 'B%')
    AND table1.cloumn2 = 'N'
    AND table1.cloumn3 != 'Y'
    GROUP BY table1.column5,
            table1.column6
) sub0
INNER JOIN table1
ON table1.id = sub0.max_id
INNER JOIN
(
    SELECT DISTINCT column1 
    FROM table2
    WHERE column2 IN ('VALUE1', 'VALUE2') 
    AND (SUBSTRING(column3,6,1) = 'Y' 
    OR SUBSTRING(column3,25,1) = 'Y')
) sub1
ON table1.column4 = sub1.column1
eivnm1vs

eivnm1vs2#

(这可能有助于 SHOW CREATE TABLE .)

AND  DATE_FORMAT(timstampColumn, '%Y/%m/%d') > DATE_ADD(CURRENT_DATE,
            INTERVAL - 28 DAY))

不能使用索引;这可能相当于:

AND  timstampColumn > CURRENT_DATE - INTERVAL 28 DAY

请提供 EXPLAIN .
你用的是什么版本?
它可能(依赖于版本)有助于 IN ( SELECT ... ) “派生”表中的子句:

JOIN ( SELECT ... ) ON ...
``` `WHERE (x,y) IN ...` 没有得到很好的优化。它们是什么类型的值?
使用*\u ci排序规则,

UPPER(LEFT(table1.cloumn1, 1)) IN ('A', 'B')

可以做到:

LEFT(table1.cloumn1, 1) IN ('A', 'B')

这对性能没有明显的帮助。最好不要为了测试而拆开柱子。
这可能会使用一个包含 `cloumn1` :

table1.cloumn1 >= 'A'
AND table1.cloumn1 < 'C'

事情的顺序和他们在一起很少有关系。中的顺序 `INDEX` 会有很大的不同。

相关问题