mysql - 我可以通过添加新索引来改进这个查询吗,或者如何改进那个查询?

标签 mysql sql drupal-7

我正在处理一个旧的遗留项目,但我遇到了查询速度非常慢的问题。

我有以下数据库架构:

table: search_api_db_full_index_text
rows : 1612226
+------------+------------------+------+-----+---------+-------+
| Field      | Type             | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+-------+
| item_id    | bigint(20)       | NO   | PRI | NULL    |       |
| field_name | varchar(255)     | NO   | PRI | NULL    |       |
| word       | varchar(50)      | NO   | PRI | NULL    |       |
| score      | int(10) unsigned | NO   |     | 0       |       |
+------------+------------------+------+-----+---------+-------+

indexes for: search_api_db_full_index_text
+-------------------------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table                         | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------------------------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| search_api_db_full_index_text |          0 | PRIMARY    |            1 | item_id     | A         |       42323 |     NULL | NULL   |      | BTREE      |         |               |
| search_api_db_full_index_text |          0 | PRIMARY    |            2 | field_name  | A         |      134023 |     NULL | NULL   |      | BTREE      |         |               |
| search_api_db_full_index_text |          0 | PRIMARY    |            3 | word        | A         |     1608286 |     NULL | NULL   |      | BTREE      |         |               |
| search_api_db_full_index_text |          1 | word_field |            1 | word        | A         |      402071 |       20 | NULL   |      | BTREE      |         |               |
| search_api_db_full_index_text |          1 | word_field |            2 | field_name  | A         |      229755 |     NULL | NULL   |      | BTREE      |         |               |
+-------------------------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+



table: search_api_db_full_index_field_event_date_mutli_field_date_opt
rows: 100421    
+---------+------------+------+-----+---------+-------+
| Field   | Type       | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+-------+
| item_id | bigint(20) | NO   | PRI | NULL    |       |
| value   | bigint(20) | NO   | PRI | NULL    |       |
+---------+------------+------+-----+---------+-------+

indexes for: search_api_db_full_index_field_event_date_mutli_field_date_opt
+----------------------------------------------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table                                                          | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------------------------------------------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| search_api_db_full_index_field_event_date_mutli_field_date_opt |          0 | PRIMARY  |            1 | item_id     | A         |       50380 |     NULL | NULL   |      | BTREE      |         |               |
| search_api_db_full_index_field_event_date_mutli_field_date_opt |          0 | PRIMARY  |            2 | value       | A         |      100760 |     NULL | NULL   |      | BTREE      |         |               |
| search_api_db_full_index_field_event_date_mutli_field_date_opt |          1 | value    |            1 | value       | A         |      100760 |     NULL | NULL   |      | BTREE      |         |               |
+----------------------------------------------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+



table: search_api_db_full_index_field_event_date_mutli_field_date_o_1
rows: 100099   
+---------+------------+------+-----+---------+-------+
| Field   | Type       | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+-------+
| item_id | bigint(20) | NO   | PRI | NULL    |       |
| value   | bigint(20) | NO   | PRI | NULL    |       |
+---------+------------+------+-----+---------+-------+

indexes for search_api_db_full_index_field_event_date_mutli_field_date_o_1
+----------------------------------------------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table                                                          | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------------------------------------------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| search_api_db_full_index_field_event_date_mutli_field_date_o_1 |          0 | PRIMARY  |            1 | item_id     | A         |       50160 |     NULL | NULL   |      | BTREE      |         |               |
| search_api_db_full_index_field_event_date_mutli_field_date_o_1 |          0 | PRIMARY  |            2 | value       | A         |      100320 |     NULL | NULL   |      | BTREE      |         |               |
| search_api_db_full_index_field_event_date_mutli_field_date_o_1 |          1 | value    |            1 | value       | A         |      100320 |     NULL | NULL   |      | BTREE      |         |               |
+----------------------------------------------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

目前,下面的查询大约需要 170 秒才能执行。

这很奇怪,因为在过去它从来没有这么慢。 (主要是 10 - 12 秒)

该查询由 Drupal View 生成,没有左连接,该查询运行得非常快。理想情况下,我想通过添加额外的索引来解决这个问题。可能吗?

SELECT SQL_NO_CACHE 
    t.item_id AS item_id,
    SUM(score) AS score,
    t.word LIKE '%test%' AS w0
FROM
    search_api_db_full_index_text t
        LEFT OUTER JOIN
    search_api_db_full_index_field_event_date_mutli_field_date_opt t_2 ON t.item_id = t_2.item_id
        LEFT OUTER JOIN
    search_api_db_full_index_field_event_date_mutli_field_date_o_1 t_3 ON t.item_id = t_3.item_id
WHERE
    ((t.word LIKE '%test%' ESCAPE '\\'))
        AND (field_name IN ('body:value' , 'field_event_organiser:title',
        'field_event_place:title',
        'field_image_caption',
        'title'))
        AND (((t_2.value >= '1474502400')
        AND (t_3.value <= '1537660799')))
GROUP BY t.item_id , item_id , w0
ORDER BY score DESC;


Output from explain:    
+------+-------------+-------+-------+---------------+---------+---------+-----------------------------------+-------+-----------------------------------------------------------+
| id   | select_type | table | type  | possible_keys | key     | key_len | ref                               | rows  | Extra                                                     |
+------+-------------+-------+-------+---------------+---------+---------+-----------------------------------+-------+-----------------------------------------------------------+
|    1 | SIMPLE      | t_2   | range | PRIMARY,value | value   | 8       | NULL                              | 35410 | Using where; Using index; Using temporary; Using filesort |
|    1 | SIMPLE      | t_3   | ref   | PRIMARY,value | PRIMARY | 8       | drupal7_.t_2.item_id              |     2 | Using where; Using index                                  |
|    1 | SIMPLE      | t     | ref   | PRIMARY       | PRIMARY | 8       | drupal7_.t_2.item_id              |    38 | Using where                                               |
+------+-------------+-------+-------+---------------+---------+---------+-----------------------------------+-------+-----------------------------------------------------------+

编辑:

如果我强制索引,查询执行时间将从 170-240 秒减少到 30-50 秒。但它仍然有点慢。

  SELECT SQL_NO_CACHE
    t.item_id AS item_id,
    SUM(score) AS score,
    t.word LIKE '%test%' AS w0
FROM
    search_api_db_full_index_text t
        LEFT OUTER JOIN
    search_api_db_full_index_field_event_date_mutli_field_date_opt t_2  FORCE INDEX (PRIMARY) ON t.item_id = t_2.item_id 
        LEFT OUTER JOIN
    search_api_db_full_index_field_event_date_mutli_field_date_o_1 t_3  FORCE INDEX (PRIMARY) ON t.item_id = t_3.item_id
WHERE
    ((t.word LIKE '%test%' ESCAPE '\\'))
        AND (field_name IN ('body:value' , 'field_event_organiser:title',
        'field_event_place:title',
        'field_image_caption',
        'title'))
        AND (((t_2.value >= '1474502400')
        AND (t_3.value <= '1537660799')))
GROUP BY t.item_id , item_id , w0
ORDER BY score DESC;

当我还强制将 search_api_db_full_index_text 上的索引设置为 word_field 时,查询会正常工作(不到 1 秒)

 SELECT SQL_NO_CACHE
    t.item_id AS item_id,
    SUM(score) AS score,
    t.word LIKE '%test%' AS w0
FROM
    search_api_db_full_index_text t FORCE INDEX (word_field)
        LEFT OUTER JOIN
    search_api_db_full_index_field_event_date_mutli_field_date_opt t_2  FORCE INDEX (PRIMARY) ON t.item_id = t_2.item_id 
        LEFT OUTER JOIN
    search_api_db_full_index_field_event_date_mutli_field_date_o_1 t_3  FORCE INDEX (PRIMARY) ON t.item_id = t_3.item_id
WHERE
    ((t.word LIKE '%test%' ESCAPE '\\'))
        AND (field_name IN ('body:value' , 'field_event_organiser:title',
        'field_event_place:title',
        'field_image_caption',
        'title'))
        AND (((t_2.value >= '1474502400')
        AND (t_3.value <= '1537660799')))
GROUP BY t.item_id , item_id , w0
ORDER BY score DESC;

最佳答案

问题在于加入 search_api_db_full_index_field_event_date_mutli_field_date_opt table 。该表的别名是 t_2,在您看到的解释结果第一行的额外列中:Using where; Using index; Using temporary; Using filesort

从性能的角度来看,使用临时文件排序非常糟糕。来自key列中您可以看到 MySQL 决定使用 value索引,支持 where子句,但不支持连接。

由于您在此表中的主键涵盖了 item_idvalue字段,我会尝试在加入 t_2 时强制 MySQL 使用主索引通过force index索引提示。显然,MySQL 优化器在这个查询中使用哪个索引做出了错误的决定。

关于mysql - 我可以通过添加新索引来改进这个查询吗,或者如何改进那个查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39644134/

相关文章:

mysql - C中一个sql语句中的多个插入

MySql 按日期对 2 个或多个表中的列进行排序

php - 如果存在则按另一个表列排序

sql - "Between"运算符在使用参数时生成错误的查询计划

Drupal 商务愿望 list 匿名

drupal-7 - Drupal 7中如何改变webform的显示样式

php - 将多个记录连接到一行?

php - 什么是 PDO,它与 SQL 注入(inject)有什么关系,我为什么要使用它?

php - mysql 请求逻辑

javascript - drupal中的自定义选择框