简体   繁体   English

使用索引导致的MySQL延迟; 使用临时; 使用文件排序

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

I have a query that joins two tables and orders the data on the primary key. 我有一个查询,该查询将两个表连接起来并按主键排序数据。 This is resulting in the very popular problem of MySQL "Using index; Using temporary; Using filesort." 这导致MySQL非常流行的问题“使用索引;使用临时文件;使用文件排序”。

The issue is causing a severe latency problem in my production tables with about 400k records. 该问题在我的具有约40万条记录的生产表中导致严重的延迟问题。

Here's more info: 这是更多信息:

I have two tables: Doctor and Area. 我有两个表:Doctor和Area。 The Doctor table has a foreign key pointing to Area. Doctor表具有指向Area的外键。

Doctor: 医生:

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

Doctor indexes: 医生索引:

+---------------+------------+------------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| 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      |         |               |
+---------------+------------+------------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

Area: 区域:

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

And the Area indexes: 面积索引:

+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| 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      |         |               |
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

I'm trying to run the following query: 我正在尝试运行以下查询:

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

The EXPLAIN returns the following (with the problematic Using index; Using temporary; Using filesort): 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                                  |
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+

If I remove the ORDER BY clause, I get the desired effect: 如果删除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                                  |
+----+-------------+---------------+-------+------------------------+------------------------+---------+--------------+------+----------------------------------------------+

Why is the ORDER BY clause causing problems here even though I'm using the primary key? 即使使用主键,为什么ORDER BY子句也会在这里引起问题?

Thank you in advance. 先感谢您。

It seems that you only have one area per doctor. 看来每个医生只有一个区域。 See how this query works: 查看此查询的工作方式:

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;

If you are using inner join to test for the presence of a doctor in the table, then add: 如果要使用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;

There is a good chance that both of these will scan the doctors table in order, picking up the information from area as needed. 这两个都很有可能会按顺序扫描doctors表,并根据需要从area获取信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM