当存在索引时,您会注意到主查询未在school_id上使用索引。如果我删除子查询并使用硬编码列表,它将使用索引。
mysql> explain SELECT year, race, CONCAT(percent,'%') as percent
-> FROM school_data_race_ethnicity as school_data_race_ethnicity_outer
-> WHERE school_id IN(
-> SELECT field_school_id_value
-> FROM field_data_field_school_id
-> WHERE entity_id IN (SELECT entity_id
-> FROM field_data_field_district
-> WHERE field_district_nid =
-> (SELECT entity_id FROM field_data_field_district_id
-> WHERE `field_district_id_value` = 26130106 LIMIT 1))
-> ) ORDER BY year DESC, race;
+----+--------------------+----------------------------------+----------------+------------------------------+-----------+---------+------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+----------------------------------+----------------+------------------------------+-----------+---------+------+-------+-----------------------------+
| 1 | PRIMARY | school_data_race_ethnicity_outer | ALL | NULL | NULL | NULL | NULL | 97116 | Using where; Using filesort |
| 2 | DEPENDENT SUBQUERY | field_data_field_school_id | ALL | NULL | NULL | NULL | NULL | 5325 | Using where |
| 3 | DEPENDENT SUBQUERY | field_data_field_district | index_subquery | entity_id,field_district_nid | entity_id | 4 | func | 1 | Using where |
| 4 | SUBQUERY | field_data_field_district_id | ALL | NULL | NULL | NULL | NULL | 685 | Using where |
+----+--------------------+----------------------------------+----------------+------------------------------+-----------+---------+------+-------+-----------------------------+
4 rows in set (0.00 sec)
mysql> describe school_data_race_ethnicity
-> ;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| school_id | varchar(255) | NO | MUL | NULL | |
| year | int(11) | NO | MUL | NULL | |
| race | varchar(255) | NO | | NULL | |
| percent | decimal(5,2) | NO | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql>
答案 0 :(得分:2)
使用INNER JOIN
代替带有IN
子句的子查询:
explain SELECT year, race, CONCAT(percent,'%') as percent
FROM school_data_race_ethnicity a
INNER JOIN(
SELECT field_school_id_value
FROM field_data_field_school_id b
INNER JOIN (SELECT entity_id
FROM field_data_field_district
WHERE field_district_nid =
(SELECT entity_id FROM field_data_field_district_id
WHERE `field_district_id_value` = 26130106 LIMIT 1)) c
ON b. entity_id = c.entity_id
) d
ON a.school_id = d.field_school_id_value
ORDER BY year DESC, race;
答案 1 :(得分:0)
服务器可能正在跳过索引搜索,因为它无法确定列表中实际有多少项。我们的想法是,由于它没有对子查询中项目数量的良好估计,因此它将选择最保守的方法并进行扫描(可能)。
我建议使用JOIN重写查询:
SELECT DISTINCT o.year, o.race, CONCAT(o.percent,'%') as percent
FROM school_data_race_ethnicity as o
INNER JOIN field_data_field_school_id s
ON s.field_school_id_value = o.school_id
INNER JOIN field_data_field_district d
ON d.entity_id = s.entity_id
WHERE field_district_nid = (
SELECT entity_id
FROM field_data_field_district_id
WHERE `field_district_id_value` = 26130106 LIMIT 1))
ORDER BY o.year DESC, o.race;