當我在兩個不同的列上運行時,我發現我的一個 MySQL 查詢存在一個奇怪的速度問題,date_from而date_to.
表結構如下:
create table if not exists table1 (
id unsigned int,
field2 int,
field3 varchar(32),
date_from date not null,
date_to date not null,
field6 text
);
create unique index idx_uniq_table1 on table1 (id, field2, field3, date_from);
create index idx_table1_id on table1 (id);
create index idx_table1_field2 on table1 (field2);
create index idx_table1_field3 on table1 (field3);
create index idx_table1_date_from on table1 (date_from);
create index idx_table1_date_to on table1 (date_to);
當我使用 運行此查詢date_from時,執行時間為 1.487 秒:
select field3, min(date_from) from table1 group by field3;
當我使用 運行另一個查詢date_to時,執行時間為 13.804 秒,幾乎慢了 10 倍:
select field3, max(date_to) from table1 group by field3;
兩列都是NOT NULL,因此沒有空值。
該表有約 7M 行。
我在這兩列之間看到的唯一區別是date_from出現在唯一索引中,但據我所知,如果不按索引中的所有四列進行過濾,那應該不會有什么不同。
我錯過了什么嗎?
這是date_from專欄的解釋:
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "889148.90"
},
"grouping_operation": {
"using_filesort": false,
"table": {
"table_name": "table1",
"access_type": "index",
"possible_keys": [
"idx_uniq_table1",
"idx_table1_id",
"idx_table1_field2",
"idx_table1_field3",
"idx_table1_date_from",
"idx_table1_date_to"
],
"key": "idx_table1_field3",
"used_key_parts": [
"field3"
],
"key_length": "130",
"rows_examined_per_scan": 5952609,
"rows_produced_per_join": 5952609,
"filtered": "100.00",
"using_index": true,
"cost_info": {
"read_cost": "293888.00",
"eval_cost": "595260.90",
"prefix_cost": "889148.90",
"data_read_per_join": "908M"
},
"used_columns": [
"id",
"field2",
"field3",
"date_from"
]
}
}
}
}
這是date_to專欄的解釋:
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "889148.90"
},
"grouping_operation": {
"using_filesort": false,
"table": {
"table_name": "table1",
"access_type": "index",
"possible_keys": [
"idx_uniq_table1",
"idx_table1_id",
"idx_table1_field2",
"idx_table1_field3",
"idx_table1_date_from",
"idx_table1_date_to"
],
"key": "idx_table1_field3",
"used_key_parts": [
"field3"
],
"key_length": "130",
"rows_examined_per_scan": 5952609,
"rows_produced_per_join": 5952609,
"filtered": "100.00",
"cost_info": {
"read_cost": "293888.00",
"eval_cost": "595260.90",
"prefix_cost": "889148.90",
"data_read_per_join": "908M"
},
"used_columns": [
"id",
"field2",
"field3",
"date_from",
"date_to"
]
}
}
}
}
我看到的唯一區別是used_columns,最后,一個包含date_to而另一個不包含。
uj5u.com熱心網友回復:
淘氣。沒有PRIMARY KEY。
由于“使用的列”似乎與查詢不一致,我不想嘗試解釋時間差異。
field3用這兩個替換索引:
INDEX(field3, date_from)
INDEX(field3, date_to)
這些將加快你的兩個選擇。
uj5u.com熱心網友回復:
除了 Rick 根據您的標準對正確索引的回答之外......速度差異的原因是一個同時具有 field3 和 date_from 的索引,引擎能夠使用實際索引中的資料而不是必須轉到包含整個記錄的原始資料頁面。只有 date_to 的索引仍然需要去每個原始資料記錄來獲取 field3,從而花費時間。
這就是您可以使用覆寫索引的原因。擁有您正在尋找的資料的每個組成部分來優化查詢。并不是說您想要一個包含 20 列的索引,但在這種情況下,過濾的常見標準正是您這樣做的原因。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/480047.html
