mysql - Mysql 多索引不适用于单个查询(Group By + Range Where 条件)
问题描述
我有一个如下查询:
Select
sum(r.impressions) as impressions from keyword_report r
where r.org_id = 1
and r.report_date between '2019-09-01' and '2019-09-10'
group by r.country, r.keyword_id;
我在keyword_report上有2个索引;
index1: (org_id, report_date)
index2: (country, keyword_id)
解释格式=json 结果:
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "138210.60"
},
"grouping_operation": {
"using_temporary_table": true,
"using_filesort": false,
"table": {
"table_name": "r",
"access_type": "ref",
"possible_keys": [
"index1",
"index2"
],
"key": "index1",
"used_key_parts": [
"org_id",
"report_date"
],
"key_length": "11",
"ref": [
"const",
"const"
],
"rows_examined_per_scan": 125646,
"rows_produced_per_join": 125646,
"filtered": "100.00",
"index_condition": "(`r`.`report_date` between '2019-09-01' and '2019-09-10')",
"cost_info": {
"read_cost": "125646.00",
"eval_cost": "12564.60",
"prefix_cost": "138210.60",
"data_read_per_join": "162M"
},
"used_columns": [
"org_id",
"keyword_id",
"impressions",
"report_date",
"country"
]
}
}
}
}
在表中,大约有;
- 1000 个不同的 org_id,
- 500 个不同的报告日期,
- 30个不同的国家,
- 1000 万个keyword_id。
我无法理解这里的两件事。
为什么使用临时的?
为什么多个索引不起作用?
结果,我该如何改进它?
解决方案
以下 JSON 输出似乎表明您的index1
索引正在被使用:
"used_key_parts": [
"org_id",
"report_date"
]
在子句期间可以使用此索引WHERE
来过滤掉不匹配的记录。在此之后,MySQL 仍然必须执行GROUP BY
聚合,其中包括对impressions
列的求和。请注意,索引对聚合并没有太大帮助,因为根据定义,数据库必须接触每个组中的每条记录来计算总和。虽然大多数时候数据库甚至不会选择在同一个表上使用两个不同的索引(但这是可能的),但在这种情况下,index2
由于聚合的性质,第二个索引在这里没有多大帮助。
举个例子,您可以使用单个索引来覆盖查询的所有步骤,请考虑以下内容:
SELECT
r.country,
MAX(r.impressions) AS max_impressions
FROM keyword_report r
WHERE
r.org_id = 1 AND
r.report_date BETWEEN '2019-09-10' AND '2019-09-10'
GROUP BY
r.country;
现在,如果您定义了以下索引:
(org_id, report_date, country, impressions)
那么 MySQL 可能会选择使用它。它会起作用,因为在过滤掉WHERE
子句中的记录后,很容易找到每个国家/地区的最大值impressions
。
推荐阅读
- android - 如何在 air sdkharman 上加载本地 html
- javascript - javascript将数据流式传输到网页的最佳实践是什么?
- python - smtplib 电子邮件不发送,脚本继续运行,没有错误消息
- postgresql - 自定义聚合函数 parallel = safe 在 postgres 13.3 中生成语法
- python - pandas.groupby 中的函数 any() 是否短路?
- python - 为子进程提供 CPU 时间和内存
- git - 2个文件夹'.git/origin'和.git/refs/remotes/origin有什么区别?
- r - 检查 data.frame 是否是另一个 data.frame 的子集
- c# - 使用 BouncyCastle 验证 Android KeyStore 签名的有效负载
- python - 如何通过python下载inta配置文件