簡體   English   中英

使用索引導致的MySQL延遲; 使用臨時; 使用文件排序

[英]MySQL latency caused by using index; Using temporary; Using filesort

我有一個查詢,該查詢將兩個表連接起來並按主鍵排序數據。 這導致MySQL非常流行的問題“使用索引;使用臨時文件;使用文件排序”。

該問題在我的具有約40萬條記錄的生產表中導致嚴重的延遲問題。

這是更多信息:

我有兩個表:Doctor和Area。 Doctor表具有指向Area的外鍵。

醫生:

+-----------------------------+---------------+------+-----+---------+----------------+
| Field                       | Type          | Null | Key | Default | Extra          |
+-----------------------------+---------------+------+-----+---------+----------------+
| id                          | int(11)       | NO   | PRI | NULL    | auto_increment |
| area_id                     | int(11)       | NO   | MUL | NULL    |                |
+-----------------------------+---------------+------+-----+---------+----------------+

醫生索引:

+---------------+------------+------------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table         | Non_unique | Key_name               | Seq_in_index | Column_name      | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+------------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| doctor        |          0 | PRIMARY                |            1 | id               | A         |        5546 |     NULL | NULL   |      | BTREE      |         |               |
| doctor        |          1 | doctor_dfd0e917        |            1 | area_id          | A         |          29 |     NULL | NULL   |      | BTREE      |         |               |
+---------------+------------+------------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

區域:

+------------------------+-------------+------+-----+---------+----------------+
| Field                  | Type        | Null | Key | Default | Extra          |
+------------------------+-------------+------+-----+---------+----------------+
| id                     | int(11)     | NO   | PRI | NULL    | auto_increment |
+------------------------+-------------+------+-----+---------+----------------+

面積索引:

+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table         | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| area          |          0 | PRIMARY  |            1 | id          | A         |          24 |     NULL | NULL   |      | BTREE      |         |               |
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

我正在嘗試運行以下查詢:

SELECT `doctor`.`id`, 
       `area`.`id` 
FROM 
       `doctor` 
INNER JOIN 
       `area` ON (`doctor`.`area_id` = `area`.`id`) 
ORDER BY 
      `doctor`.`id` DESC LIMIT 100;

EXPLAIN返回以下內容(帶有問題的“使用”索引;“使用臨時”;“使用文件排序”):

+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+
| id | select_type | table         | type  | possible_keys          | key                    | key_len | ref          | rows | Extra                                        |
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+
|  1 | SIMPLE      | area          | index | PRIMARY                | PRIMARY                | 4       | NULL         |   24 | Using index; Using temporary; Using filesort |
|  1 | SIMPLE      | doctor        | ref   | doctor_dfd0e917        | doctor_dfd0e917        | 4       | area.id      |  191 | Using index                                  |
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+

如果刪除ORDER BY子句,則會達到預期的效果:

+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+
| id | select_type | table         | type  | possible_keys          | key                    | key_len | ref          | rows | Extra                                        |
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+
|  1 | SIMPLE      | area          | index | PRIMARY                | PRIMARY                | 4       | NULL         |   24 | Using index                                  |
|  1 | SIMPLE      | doctor        | ref   | doctor_dfd0e917        | doctor_dfd0e917        | 4       | area.id      |  191 | Using index                                  |
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+

即使使用主鍵,為什么ORDER BY子句也會在這里引起問題?

先感謝您。

看來每個醫生只有一個區域。 查看此查詢的工作方式:

SELECT d.id,
       (SELECT a.id FROM area a ON a.id = d.area_id) as area_id
FROM doctor d 
ORDER BY d.id DESC
LIMIT 100;

如果要使用inner join測試表中是否存在醫生,請添加:

SELECT d.id,
       (SELECT a.id FROM area a ON a.id = d.area_id) as area_id
FROM doctor d 
WHERE EXISTS (SELECT 1 FROM area a ON a.id = d.area_id)
ORDER BY d.id DESC
LIMIT 100;

這兩個都很有可能會按順序掃描doctors表,並根據需要從area獲取信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM