Mysql

為什麼 MySQL 在查詢中忽略我的索引?

  • May 14, 2019

我在生產數據庫伺服器(主伺服器)中有以下查詢:

SELECT  * 
FROM Enlace_llamadas 
where id_empresa IN (1,5,33,36,40,44,48,53,55,111,115,125,127,151,167,175,181,185,187,189,195,199,201,203,207,209,221,223,231,233,239,241,243,244,247,249,251,253,257,259,261,276,277,281,283,287,291,293,301,305,307,313,315,319,323,339,341,343,345,359,367,371,379,381,383,385,387,391,393,395,397,421,423,425,429,431,433,437,439,441,445,447,451,454,463,469,477,479,481,489,491,495,497,501,507,510,514,520,522) 
 AND date(fecha_inicio)=date(NOW()) 
 and Enlace_llamadas.fecha_fin='0000-00-00 00:00:00'
 and TIMESTAMPDIFF(MINUTE,fecha_inicio, NOW()) >= '5';

在此伺服器中執行 EXPLAIN,結果如下:

+----+-------------+-----------------+------+------------------------------------------------------------------------+------+---------+------+----------+-------------+
| id | select_type | table           | type | possible_keys                                                          | key  | key_len | ref  | rows     | Extra       |
+----+-------------+-----------------+------+------------------------------------------------------------------------+------+---------+------+----------+-------------+
|  1 | SIMPLE      | Enlace_llamadas | ALL  | id_empresa_id_agente,idx_empresa_campana,id_empresa_cliente,id_empresa | NULL | NULL    | NULL | 41330453 | Using where |
+----+-------------+-----------------+------+------------------------

此查詢需要很長時間,執行時間將近 40 秒,並且機器資源使用大量 CPU 超過 0f 500%。執行SHOW INDEX FROM nombre_tabla,這是結果表。

| Enlace_llamadas |          0 | PRIMARY                  |            1 | id                | A         |    41330863 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_campana               |            1 | id_campana        | A         |       19700 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_cliente               |            1 | id_cliente        | A         |    41330863 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_numero_cliente        |            1 | id_numero_cliente | A         |    41330863 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_empresa_id_agente     |            1 | id_empresa        | A         |          18 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_empresa_id_agente     |            2 | id_agente         | A         |       19468 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | idx_empresa_campana      |            1 | id_empresa        | A         |          18 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | idx_empresa_campana      |            2 | id_campana        | A         |       19569 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_empresa_cliente       |            1 | id_empresa        | A         |          18 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_empresa_cliente       |            2 | id_cliente        | A         |    41330863 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | i_Enlace_llamadas_fechas |            1 | fecha_inicio      | A         |    41330863 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | i_Enlace_llamadas_fechas |            2 | fecha_fin         | A         |    41330863 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_agente                |            1 | id_agente         | A         |        8516 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_empresa               |            1 | id_empresa        | A         |          18 |     NULL | NULL   |      | BTREE      |         |               |
+-----------------+------------+--------------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
14 rows in set (0.00 sec)

另一個伺服器(從屬伺服器)中的相同查詢需要 0.21 秒。這是從伺服器中的執行計劃。

id   | select_type | table           | type | possible_keys                                                                                   | key                      | key_len | ref   | rows | Extra                              |
+------+-------------+-----------------+------+-------------------------------------------------------------------------------------------------+--------------------------+---------+-------+------+------------------------------------+
|    1 | SIMPLE      | Enlace_llamadas | ref  | id_empresa,i_Enlace_llamadas_fechas,id_empresa_id_agente,id_empresa_cliente,idx_empresa_campana | i_Enlace_llamadas_fechas | 8       | const |  276 | Using index condition; Using where

此伺服器上此表的索引

| Table           | Non_unique | Key_name                 | Seq_in_index | Column_name       | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------+------------+--------------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Enlace_llamadas |          0 | PRIMARY                  |            1 | id                | A         |    46034401 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_campana               |            1 | id_campana        | A         |       78826 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_cliente               |            1 | id_cliente        | A         |    46034401 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_numero_cliente        |            1 | id_numero_cliente | A         |    46034401 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_agente                |            1 | id_agente         | A         |        9389 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_empresa               |            1 | id_empresa        | A         |          18 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | i_Enlace_llamadas_fechas |            1 | fecha_fin         | A         |    46034401 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | i_Enlace_llamadas_fechas |            2 | fecha_inicio      | A         |    46034401 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_empresa_id_agente     |            1 | id_empresa        | A         |          18 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_empresa_id_agente     |            2 | id_agente         | A         |       42663 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_empresa_cliente       |            1 | id_empresa        | A         |          18 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | id_empresa_cliente       |            2 | id_cliente        | A         |    46034401 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | idx_empresa_campana      |            1 | id_empresa        | A         |          18 |     NULL | NULL   |      | BTREE      |         |               |
| Enlace_llamadas |          1 | idx_empresa_campana      |            2 | id_campana        | A         |       22271 |     NULL | NULL   |      | BTREE      |         |               |
+-----------------+------------+--------------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
14 rows in set (0.00 sec)

這是什麼原因?

正確格式化輸出後,您可以看到i_Enlace_llamadas_fechas兩個伺服器之間的定義不同——第二個伺服器中的列順序顛倒了,這使得它適合那裡的查詢。

如果您需要對它們進行索引,請不要隱藏函式中的列。

AND date(fecha_inicio)=date(NOW())

如果fecha_inicio是類型DATE,只需執行

AND fecha_inicio = CURDATE()

如果是DATETIME,那麼做

AND fecha_inicio >= CURDATE()
AND fecha_inicio  < CURDATE() + INTERVAL 1 DAY

這是在做什麼?

and TIMESTAMPDIFF(MINUTE,fecha_inicio, NOW()) >= '5';

如果它正在檢查它是否在最後 5 分鐘內,只需執行

AND fecha_inicio > NOW() - INTERVAL 5 MINUTE

並擺脫日期測試(除非跨越午夜有什麼特別之處)。

然後有這個複合索引:

INDEX(fecha_fin, id_empresa, fecha_inicio)  -- in this  order

如果您需要進一步討論,請提供

SHOW CREATE TABLE
MySQL version
Size of tables

引用自:https://dba.stackexchange.com/questions/238053