[英]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: 据我所知,您的子查询是瓶颈:
LTocMapping.CONTACT_ID
对于第一LTocMapping.CONTACT_ID
查询,您正在使用LTocMapping.CONTACT_ID
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.