MySQL 范围查询很慢

标签 mysql sql

我已经阅读了不同的链接,例如 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 并报告:

enter image description here

这是我尝试过的另一个查询。

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/

相关文章:

mysql - ruby rails : Why first active record query takes longer?

php - 从 MySQL 中的两个连接表中获取多个计数

mysql - 更新具有 IN 和 NOT IN 的查询的替代方法

SQL查询仅获取另一列中只有1个值的那些行

mysql - 从表中计算每隔一行的时间差

sql - 从另一个没有临时表的选择中选择?

php - 如何通过一个查询检查多个表中是否存在行?

mysql - 如何简化MySQL中的序列数据?

sql - 使用 json_agg 从 SQL 查询获取 [null] 响应

mysql - SQL 查询以显示包括产品图像在内的最新订单信息 (Prestashop)