我已经阅读了不同的链接,例如 http://goo.gl/1nr3s2 , http://goo.gl/gv4Vlc和其他 stackoverflow 问题,但没有一个能帮助我解决这个问题。
此问题与多个表交互,但 EXPLAIN 方法帮助我识别范围是查询的主要问题。
首先我需要解释一下,我有这个表和这个示例数据(我不会在任何表中使用 id 来简化过程)
+-------+----------+----------------+--------------+---------------+----------------+
| marca | submarca | modelo_inicial | modelo_final | motor | texto_articulo |
+-------+----------+----------------+--------------+---------------+----------------+
| Buick | Century | 1993 | 1996 | 4 Cil 2.2 Lts | BE1254AG4 |
| Buick | Century | 1993 | 1996 | 4 Cil 2.2 Lts | 854G4 |
+-------+----------+----------------+--------------+---------------+----------------+
这个表有超过150万行,我创建了一个索引,将initial_year和end_year合并为一个索引,initial_year有一个索引,end_year有一个独立的索引,这样的结构。
CREATE TABLE `general` (
`id_general` int(11) NOT NULL AUTO_INCREMENT,
`id_marca_submarca` int(11) NOT NULL,
`id_modelo_inicial` int(11) NOT NULL,
`id_modelo_final` int(11) NOT NULL,
`id_motor` int(11) NOT NULL,
`id_articulo` int(11) NOT NULL,
PRIMARY KEY (`id_general`),
KEY `fk_general_articulo` (`id_articulo`),
KEY `modelo_inicial_final` (`id_modelo_inicial`,`id_modelo_final`),
KEY `indice_motor` (`id_motor`),
KEY `indice_marca_submarca` (`id_marca_submarca`),
KEY `indice_modelo_inicial` (`id_modelo_inicial`),
KEY `indice_modelo_final` (`id_modelo_final`),
CONSTRAINT `fk_general_articulo` FOREIGN KEY (`id_articulo`) REFERENCES `articulo` (`id_articulo`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1191853 DEFAULT CHARSET=utf8
我有另一个包含不同年份的表,就像这个样本数据:
+---------+----------------+
| id_modelo | texto_modelo |
+-----------+--------------+
| 76 | 2014 |
| 75 | 2013 |
............................
| 1 | 1939 |
+-----------+--------------+
我创建了一个包含子查询的查询来获取特定数据,但花了很多时间。我会提出一些我已经尝试过但对我来说没有一个能正常工作的问题
SELECT DISTINCT M.texto_modelo
FROM general G
INNER JOIN parque_vehicular.modelo M ON G.id_modelo_inicial <= M.id_modelo AND G.id_modelo_final >= M.id_modelo
WHERE EXISTS
(
SELECT DISTINCT A.id_articulo
...subquery...
WHERE A.id_articulo = G.id_articulo AND AD.id_distribuidor = 1
)
ORDER BY M.texto_modelo DESC;
这个查询花费了很多秒,所以我使用 EXPLAIN 并报告:
这是我尝试过的另一个查询。
SELECT DISTINCT M.texto_modelo
FROM general G
INNER JOIN parque_vehicular_rigs.modelo M ON M.id_modelo BETWEEN G.id_modelo_inicial AND G.id_modelo_final
WHERE EXISTS
(
SELECT DISTINCT A.id_articulo
...subquery WHERE A.id_articulo = G.id_articulo AND AD.id_distribuidor = 1
)
ORDER BY M.texto_modelo DESC;
最佳答案
您可以执行一些操作来更改查询计划:
- OP1:删除表
general
中的所有键或索引。 - OP2:在 EXISTS 的子查询中使用
SELECT 1
而不是SELECT DISTINCT A.id_articulo
。
分别做这些操作,比较差异。
关于MySQL 范围查询很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26541989/