【发布时间】:2018-05-15 14:17:29
【问题描述】:
我正在使用 MySQL 5.6 并且有一个由 DATE 类型的“network_date”列分区的表(每天都有 一个分区,例如“2018-05-01”,每个分区包含大约 400,000 行)。该表有两个复合索引(不是唯一的),其中也包括“network_date”列(首先按 6 列的顺序)。索引是:
- _daily_ad_level_demand_idx:network_date、publisher_network_id、display_advertiser_id、business_rule_id、campaign_id、ad_id
- _daily_ad_level_supply_idx:network_date、publisher_network_id、publisher_id、widget_id
但是,根据 EXPLAIN 命令,在运行以下查询时:
EXPLAIN EXTENDED SELECT
network_date,
SUM(COALESCE(ad_view, 0)) AS ad_view,
SUM(COALESCE(ad_spend_network, 0)) AS ad_spend_network,
SUM(COALESCE(ad_click, 0)) AS ad_click,
campaign_id,
display_advertiser_id,
publisher_network_id,
ad_id
FROM
daily_ad_level
WHERE
(publisher_network_id = 16020)
AND network_date BETWEEN STR_TO_DATE('2018-04-15 00:00:00.000000',
'%Y-%m-%d %H:%i:%S.%f') AND STR_TO_DATE('2018-05-12 23:59:59.999000',
'%Y-%m-%d %H:%i:%S.%f')
GROUP BY campaign_id, network_date, display_advertiser_id,
publisher_network_id, ad_id
优化器没有选择索引,并且正在进行全表扫描。 你可以在这里看到结果: EXPLAIN command output with 'network_date' included in index
在做了一些研究并对此感到困惑之后,我决定从索引中删除“network_date”列 - 分区修剪无论如何都应该进行必要的查找,因此将它包含在索引中似乎是多余的。再次运行 EXPLAIN 命令显示现在正在选择一个索引。你可以在这里看到结果: EXPLAIN command output with no 'network_date' included in index
在查询持续时间方面,优化器选择索引时性能下降:从 9.75 秒到 12.4 秒...问题是为什么???
分析 first explain 命令输出(没有使用索引的那个),可以看到 'filtered' 和 'rows' 列的值分别为 50.00 和 4,474,281。是不是优化器推断出全表扫描比使用只消除大约一半行的索引便宜? 如果是这样,我希望在第二种情况下会出现相同的行为,但事实并非如此:优化器选择了一个索引并且查询执行得很差。
有人知道可能导致这种行为的原因吗?
【问题讨论】:
-
在这里猜测:包含
network_date的优化器可以看到您的条件不是很严格,因此它选择表扫描。没有它,优化器会看到publisher_network_id可能非常严格,所以它使用索引方法,即使实际上它更慢。 -
你能显示
SHOW CREATE TABLE daily_ad_level -
@RaymondNijland 创建表脚本太长...该表有 500 个分区和 70 列。我认为重要的是要提到该表有 no 主键
-
我不知道该表在哪个引擎上运行。但我知道在 InnoDB 表上没有主键是不好的...我在 dba 上发布了我的一个小警告帖子stackexchange 关于为什么你应该在 InnoDB 表中始终拥有 PRIMARY KEY 或 UNIQUE 键dba.stackexchange.com/questions/48072/…
-
@RaymondNijland 忘了说:InnoDB 存储引擎
标签: mysql database database-performance query-performance