gpt4 book ai didi

MySql 没有为少数查询选择正确的索引

转载 作者:行者123 更新时间:2023-11-29 04:40:56 25 4
gpt4 key购买 nike

我在表上运行以下查询,我在 where 条件下更改值,而在一种情况下运行它采用一个索引,而另一种情况采用另一个(错误的??)索引。

查询 1 的行数是 402954,大约需要 1.5 秒

查询 2 的行数是 52097,大约需要 35 秒

两个查询 query 1 和 query 2 是相同的,只是我在 where 条件下改变值

查询 1

EXPLAIN SELECT 
log_type,count(DISTINCT subscriber_id) AS distinct_count,
count(subscriber_id) as total_count
FROM campaign_logs
WHERE
domain = 'xxx' AND
campaign_id='123' AND
log_type IN ('EMAIL_SENT', 'EMAIL_CLICKED', 'EMAIL_OPENED', 'UNSUBSCRIBED') AND
log_time BETWEEN
CONVERT_TZ('2015-02-12 00:00:00','+05:30','+00:00') AND
CONVERT_TZ('2015-02-19 23:59:58','+05:30','+00:00')
GROUP BY log_type;

上述查询的解释

+----+-------------+---------------+-------+------------------------------------------------------------------------------------------------------+-----------------------------------------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+-------+------------------------------------------------------------------------------------------------------+-----------------------------------------+---------+------+--------+-------------+
| 1 | SIMPLE | campaign_logs | range | campaign_id_index,domain_index,log_type_index,log_time_index,campaignid_domain_logtype_logtime_index | campaignid_domain_logtype_logtime_index | 468 | NULL | 402954 | Using where |
+----+-------------+---------------+-------+------------------------------------------------------------------------------------------------------+-----------------------------------------+---------+------+--------+-------------+

查询 2

EXPLAIN SELECT 
log_type,count(DISTINCT subscriber_id) AS distinct_count,
count(subscriber_id) as total_count
FROM stats.campaign_logs
WHERE
domain = 'yyy' AND
campaign_id='345' AND
log_type IN ('EMAIL_SENT', 'EMAIL_CLICKED', 'EMAIL_OPENED', 'UNSUBSCRIBED') AND
log_time BETWEEN
CONVERT_TZ('2014-02-05 00:00:00','+05:30','+00:00') AND
CONVERT_TZ('2015-02-19 23:59:58','+05:30','+00:00')
GROUP BY log_type;

解释上面的查询

+----+-------------+---------------+-------------+------------------------------------------------------------------------------------------------------+--------------------------------+---------+------+-------+------------------------------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+-------------+------------------------------------------------------------------------------------------------------+--------------------------------+---------+------+-------+------------------------------------------------------------------------------+
| 1 | SIMPLE | campaign_logs | index_merge | campaign_id_index,domain_index,log_type_index,log_time_index,campaignid_domain_logtype_logtime_index | campaign_id_index,domain_index | 153,153 | NULL | 52097 | Using intersect(campaign_id_index,domain_index); Using where; Using filesort |
+----+-------------+---------------+-------------+------------------------------------------------------------------------------------------------------+--------------------------------+---------+------+-------+------------------------------------------------------------------------------+

查询 1 使用了正确的索引,因为我有复合索引

查询 2 正在使用索引合并,执行时间很长

为什么MySql对同一个查询使用不同的索引

我知道我们可以在查询中提及 USE INDEX,但为什么 MySql 在这种情况下没有选择正确的索引??。我做错了什么吗??

最佳答案

不,你没有做错任何事。

正如Chipmonkey在评论中所述,有时MySQL会因为过时的表统计信息而选择错误的执行计划。您可以通过执行 ANALYZE TABLE 更新表统计信息。

不过,MySQL 优化器并没有那么复杂。它看到在这两种情况下,MySQL 都必须访问两个二级索引,然后对聚簇索引执行查找以获取实际的表数据,因此当它看到也许第二个查询通过使用两个单独的索引具有更好的选择性并合并它们,你不能仅仅因为它猜错了就责怪它。

我猜测,如果您有一个覆盖 索引,这样 MySQL 就可以仅使用该索引执行整个查询,那么它会更倾向于该索引而不是执行合并。

尝试将 subscriber_id 添加到多列索引的末尾以获得覆盖索引。

否则,请使用USE INDEXFORCE INDEX,因为这就是它们的用途。您比 MySQL 更了解数据。

关于MySql 没有为少数查询选择正确的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28697890/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com