我正在处理一个旧的遗留项目,但我遇到了查询速度非常慢的问题。
我有以下数据库架构:
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_id
和 value
字段,我会尝试在加入 t_2
时强制 MySQL 使用主索引通过force index索引提示。显然,MySQL 优化器在这个查询中使用哪个索引做出了错误的决定。
关于mysql - 我可以通过添加新索引来改进这个查询吗,或者如何改进那个查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39644134/