MySql 查询速度慢 1000 倍,LIMIT 稍高(不偏移)
MySql query 1000x slower with slighty higher LIMIT (not offset)
我有一个包含大约 12Mio 记录的 MySQL 数据库。现在我使用以下查询从该数据库中查询所需的行:
SELECT date_time, price_l0, amount_l0, price_l1, amount_l1, price_l2, amount_l2, price_l3, /* 34 more columns */
FROM book_states
WHERE date_time > ? and
date_time < ? and
bookID = ?
ORDER BY date_time ASC
LIMIT 4350
问题是当我使用约 4340 的 LIMIT 时,此查询大约需要 0.002/0.15 秒 到 运行 .但是,如果我使用 4350 的限制,则需要 3.0/0.15 秒 (!) 到 运行.
如果我 select 更少的列,那么非常快和非常慢的查询之间的阈值会稍微高一些,但即使我 select 只有一列,也需要 3 秒或更多,如果 LIMIT 是超过 5000.
现在我怀疑这是一个 MySQL 设置问题或某种 RAM 限制,但由于我无论如何都不是 MySQL 专家,所以我要求你解释是什么原因造成的这个严重的性能问题。
编辑:
这是 JSON 解释查询的数据,该查询耗时 3 秒
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "282333.60"
},
"ordering_operation": {
"using_filesort": true,
"table": {
"table_name": "book_states",
"access_type": "ref",
"possible_keys": [
"index1",
"index2",
"index3"
],
"key": "index2",
"used_key_parts": [
"bookID"
],
"key_length": "2",
"ref": [
"const"
],
"rows_examined_per_scan": 235278,
"rows_produced_per_join": 81679,
"filtered": "34.72",
"index_condition": "(`datastore`.`book_states`.`bookID` <=> 29)",
"cost_info": {
"read_cost": "235278.00",
"eval_cost": "16335.84",
"prefix_cost": "282333.60",
"data_read_per_join": "14M"
},
"used_columns": [
"id",
"date_time",
"bookID"
],
"attached_condition": "((`datastore`.`book_states`.`date_time` > '2018-09-28T16:18:49') and (`datastore`.`book_states`.`date_time` < '2018-09-29T23:18:49'))"
}
}
}
}
您查询的最佳索引是:(bookID, date_time)
。注意列的顺序,这很重要。
MySQL 正在努力使用现有索引优化您的查询。它可以 select 记录,使用您提到的索引的 date_time
部分(或使用 bookId)
上的索引,然后对结果进行排序。
或者,它可以扫描您的复合索引(其中包含按 date/time 排序的记录),过滤掉不需要的书籍。
这两种方法之间的选择就是您(大概)看到的。哪个更好取决于收集的统计数据,它们必然只提供部分信息。
因此,切换索引中的列,问题就会消失,至少对于这个特定的查询。
我有一个包含大约 12Mio 记录的 MySQL 数据库。现在我使用以下查询从该数据库中查询所需的行:
SELECT date_time, price_l0, amount_l0, price_l1, amount_l1, price_l2, amount_l2, price_l3, /* 34 more columns */
FROM book_states
WHERE date_time > ? and
date_time < ? and
bookID = ?
ORDER BY date_time ASC
LIMIT 4350
问题是当我使用约 4340 的 LIMIT 时,此查询大约需要 0.002/0.15 秒 到 运行 .但是,如果我使用 4350 的限制,则需要 3.0/0.15 秒 (!) 到 运行.
如果我 select 更少的列,那么非常快和非常慢的查询之间的阈值会稍微高一些,但即使我 select 只有一列,也需要 3 秒或更多,如果 LIMIT 是超过 5000.
现在我怀疑这是一个 MySQL 设置问题或某种 RAM 限制,但由于我无论如何都不是 MySQL 专家,所以我要求你解释是什么原因造成的这个严重的性能问题。
编辑: 这是 JSON 解释查询的数据,该查询耗时 3 秒
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "282333.60"
},
"ordering_operation": {
"using_filesort": true,
"table": {
"table_name": "book_states",
"access_type": "ref",
"possible_keys": [
"index1",
"index2",
"index3"
],
"key": "index2",
"used_key_parts": [
"bookID"
],
"key_length": "2",
"ref": [
"const"
],
"rows_examined_per_scan": 235278,
"rows_produced_per_join": 81679,
"filtered": "34.72",
"index_condition": "(`datastore`.`book_states`.`bookID` <=> 29)",
"cost_info": {
"read_cost": "235278.00",
"eval_cost": "16335.84",
"prefix_cost": "282333.60",
"data_read_per_join": "14M"
},
"used_columns": [
"id",
"date_time",
"bookID"
],
"attached_condition": "((`datastore`.`book_states`.`date_time` > '2018-09-28T16:18:49') and (`datastore`.`book_states`.`date_time` < '2018-09-29T23:18:49'))"
}
}
}
}
您查询的最佳索引是:(bookID, date_time)
。注意列的顺序,这很重要。
MySQL 正在努力使用现有索引优化您的查询。它可以 select 记录,使用您提到的索引的 date_time
部分(或使用 bookId)
上的索引,然后对结果进行排序。
或者,它可以扫描您的复合索引(其中包含按 date/time 排序的记录),过滤掉不需要的书籍。
这两种方法之间的选择就是您(大概)看到的。哪个更好取决于收集的统计数据,它们必然只提供部分信息。
因此,切换索引中的列,问题就会消失,至少对于这个特定的查询。