简体   繁体   English

Mysql查询性能很慢

[英]Mysql Query performance very slow

The below query was taking more than 8 min and 900 000 rows processed. 以下查询耗时8分钟以上,处理了90万行。 it is very slow and affect my product. 这很慢,会影响我的产品。 I can't identify why the query getting slow, all index are set fine. 我无法确定为什么查询变慢,所有索引设置都很好。

explain SELECT 
    COUNT(DISTINCT (cinfo.CONTACT_ID))
FROM
    cinfo
        INNER JOIN
    LTocMapping ON cinfo.CONTACT_ID = LTocMapping.CONTACT_ID
WHERE
    (((((((((cinfo.COUNTRY LIKE '%Panama%')
        OR (cinfo.COUNTRY LIKE '%PANAMA%'))
        AND (((cinfo.CONTACT_EMAIL NOT LIKE '%test%')
        AND (cinfo.CONTACT_EMAIL NOT LIKE '%engine%'))
        OR (cinfo.CONTACT_EMAIL IS NULL)))
        AND ((SELECT 
            (GROUP_CONCAT(Temp.LIST_ID
                    ORDER BY Temp.LIST_ID) REGEXP ('.*,*221715000514445053,*.*$'))
            FROM
                LTocMapping Temp
            WHERE
                ((LTocMapping.CONTACT_ID = Temp.CONTACT_ID)
                    AND (((Temp.MAPPING_ID >= 221715000000000000)
                    AND (Temp.MAPPING_ID <= 221715999999999999))
                    OR ((Temp.MAPPING_ID >= 0)
                    AND (Temp.MAPPING_ID <= 999999999999))))
            GROUP BY Temp.CONTACT_ID) = '0'))
        AND ((SELECT 
            (GROUP_CONCAT(Temp.LIST_ID
                    ORDER BY Temp.LIST_ID) REGEXP ('.*,*221715000520574130,*.*$'))
            FROM
                LTocMapping Temp
            WHERE
                ((LTocMapping.CONTACT_ID = Temp.CONTACT_ID)
                    AND (((Temp.MAPPING_ID >= 221715000000000000)
                    AND (Temp.MAPPING_ID <= 221715999999999999))
                    OR ((Temp.MAPPING_ID >= 0)
                    AND (Temp.MAPPING_ID <= 999999999999))))
            GROUP BY Temp.CONTACT_ID) = '0'))
        AND (LTocMapping.LIST_ID IN (221715000520574130 , 221715000201569885)))
        AND (LTocMapping.STATUS = BINARY 'subscribed'))
        AND (((cinfo.CONTACT_STATUS = BINARY 'active')
        OR (cinfo.CONTACT_STATUS = BINARY 'softbounce'))
        AND (LTocMapping.STATUS = BINARY 'subscribed')))
        AND (((cinfo.CONTACT_ID >= 221715000000000000)
        AND (cinfo.CONTACT_ID <= 221715999999999999))
        OR ((cinfo.CONTACT_ID >= 0)
        AND (cinfo.CONTACT_ID <= 999999999999))))

And the answer will be 答案将是

在此处输入图片说明

Below tables FYR 下表FYR

Table 1 : 表格1 :

mysql> desc cinfo;
+------------------------+--------------+------+-----+-----------+-------+
| Field                  | Type         | Null | Key | Default   | Extra |
+------------------------+--------------+------+-----+-----------+-------+
| CONTACT_ID             | bigint(19)   | NO   | PRI | NULL      |       |
| CONTACT_EMAIL          | varchar(100) | NO   | MUL | NULL      |       |
| TITLE                  | varchar(20)  | YES  |     | NULL      |       |
| FIRSTNAME              | varchar(100) | YES  |     | NULL      |       |
| LASTNAME               | varchar(50)  | YES  |     | NULL      |       |     |
| ADDED_BY               | varchar(20)  | YES  |     | NULL      |       |
| ADDED_TIME             | bigint(19)   | NO   |     | NULL      |       |
| LAST_UPDATED_TIME      | bigint(19)   | NO   |     | NULL      |       |
+------------------------+--------------+------+-----+-----------+-------+

Table 2 : 表2:

 mysql> desc LTocMapping;
+---------------------+--------------+------+-----+------------+-------+
| Field               | Type         | Null | Key | Default    | Extra |
+---------------------+--------------+------+-----+------------+-------+
| MAPPING_ID          | bigint(19)   | NO   | PRI | NULL       |       |
| CONTACT_ID          | bigint(19)   | NO   | MUL | NULL       |       |
| LIST_ID             | bigint(19)   | NO   | MUL | NULL       |       |
| STATUS              | varchar(100) | YES  |     | subscribed |       |
| MAPPING_STATUS      | varchar(20)  | YES  |     | connected  |       |
| MAPPING_TIME        | bigint(19)   | YES  |     | NULL       |       |
+---------------------+--------------+------+-----+------------+-------+

As Far as I can tell, your subqueries are the bottleneck: 据我所知,您的子查询是瓶颈:

  • For the first subquery, you are using LTocMapping.CONTACT_ID 对于第一LTocMapping.CONTACT_ID查询,您正在使用LTocMapping.CONTACT_ID
  • For the second subquery, you are using LTocMapping.CONTACT_ID as well. 对于第二LTocMapping.CONTACT_ID查询,您LTocMapping.CONTACT_ID使用LTocMapping.CONTACT_ID

These references (to values of the outer query) are causing these inner queries to become correlated subqueries (also called dependent subqueries ). 这些引用(对外部查询的值的引用)使这些内部查询成为correlated subqueries (也称为dependent subqueries )。 And that means: For every row you are going to fetch on one of the outer tables (~970000) - you are firing 2 additional queries on another table. 这意味着:对于每一行,您将在一个外部表上获取数据(〜970000)-您将在另一个表上触发2个附加查询。

So, that's 1.8 Million (as it seems as well not trivial) queries you are executing. 因此,这就是您正在执行的180万个查询(看起来并不琐碎)。

Most the time, a correlated subquery can be replaced by a proper join. 大多数时候,相关的子查询可以用适当的联接代替。 But this depends on the usecase. 但这取决于用例。 You also can join the same table twice, when using a different alias. 使用不同的别名时,您也可以两次连接同一张表。

But to outline some join-options, you need to explain, why the subqueries resulting in the condition group_concat(....) = '0' are important - or maybe better, what you want to achieve. 但是要概述一些连接选项,您需要解释为什么导致条件group_concat(....) = '0'的子查询很重要-也许更好地是您想要实现的目标。

(ps.: You can also see, that explain outlines them as dependent subquery ) (ps .:您还可以看到,该explain将它们概述为dependent subquery

OR is inefficient, see if you can avoid it. OR效率低下,看看是否可以避免。

Leading wildcards in LIKE are inefficient. LIKE中的通配符无效。 See if a FULLTEXT index would work for you. 查看FULLTEXT索引是否适合您。

With a proper COLLATION , you don't need to test both upper and lower case. 使用正确的COLLATION ,您无需同时测试大小写。 Also you can avoid use of BINARY . 您也可以避免使用BINARY In both cases, you might be able to use an index. 在这两种情况下,您都可以使用索引。 (What indexes do you have?) (您有什么索引?)

Try to change from 尝试从

WHERE ( ( SELECT ... ) = '0' )

to

WHERE ( NOT EXISTS ( SELECT ... ) )

(The SELECT will need some modification.) SELECT将需要进行一些修改。)

(Please get rid of some of the redundant parens; it is hard to read.) (请删除一些多余的括号;很难阅读。)

(Please use SHOW CREATE TABLE ; it is more descriptive than DESCRIBE .) (请使用SHOW CREATE TABLE ;它比DESCRIBE更具描述性。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM