我将 Drupal 6 与 MySQL 5.0.95 版一起使用,我的一个查询显示基于最新文章日期的内容速度变慢,并且由于使用频率而完全破坏了网站性能,这让我陷入了僵局。有问题的查询如下:
SELECT n.nid,
n.title,
ma.field_article_date_format_value,
ma.field_article_summary_value
FROM node n
INNER JOIN content_type_article ma ON n.nid=ma.nid
INNER JOIN term_node tn ON n.nid=tn.nid
WHERE tn.tid= 153
AND n.status=1
ORDER BY ma.field_article_date_format_value DESC
LIMIT 0, 11;
查询的 EXPLAIN 显示以下结果:
+----+-------------+-------+--------+--------------------------+---------+---------+----------------------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+--------------------------+---------+---------+----------------------+-------+---------------------------------+
| 1 | SIMPLE | tn | ref | PRIMARY,nid | PRIMARY | 4 | const | 19006 | Using temporary; Using filesort |
| 1 | SIMPLE | ma | ref | nid,ix_article_date | nid | 4 | drupal_mm_stg.tn.nid | 1 | |
| 1 | SIMPLE | n | eq_ref | PRIMARY,node_status_type | PRIMARY | 4 | drupal_mm_stg.ma.nid | 1 | Using where |
+----+-------------+-------+--------+--------------------------+---------+---------+----------------------+-------+---------------------------------+
这个查询看起来相对简单直接,检索属于类别(术语)153 且状态为 1(已发布)的文章。但显然,使用临时表和使用文件排序意味着查询必然会失败,据我所知浏览它。
从 ORDER BY 子句中移除 field_article_date_format_value 解决了 Using temporary;使用 filesort 减少了查询执行时间,但这是必需的并且不能权衡取舍,不幸的是,这同样适用于网站性能。
我的预感是,大部分问题来自于将文章映射到类别的 term_node 表,它是一个多对多关系表,这意味着如果文章 X 与 5 个类别 C1....C5 相关联,它将有 5 个条目该表,该表来自开箱即用的 drupal。
处理大量的数据库内容对我来说是新事物,并且经历了一些类似的查询( When ordering by date desc, "Using temporary" slows down query , MySQL performance optimization: order by datetime field ) 我试图为 content_type_article 创建一个复合索引,其 datetime 字段在 ORDER BY 子句中与其中的另一个键 (nid) 一起使用,并尝试 FORCE INDEX。
SELECT n.nid, n.title,
ma.field_article_date_format_value,
ma.field_article_summary_value
FROM node n
INNER JOIN content_type_article ma FORCE INDEX (ix_article_date) ON n.nid=ma.nid
INNER JOIN term_node tn ON n.nid=tn.nid
WHERE tn.tid= 153
AND n.status=1
ORDER BY ma.field_article_date_format_value DESC
LIMIT 0, 11;
结果和下面的 EXPLAIN 查询似乎没有多大帮助
+----+-------------+-------+--------+--------------------------+-----------------+---------+----------------------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+--------------------------+-----------------+---------+----------------------+-------+---------------------------------+
| 1 | SIMPLE | tn | ref | PRIMARY,nid | PRIMARY | 4 | const | 18748 | Using temporary; Using filesort |
| 1 | SIMPLE | ma | ref | ix_article_date | ix_article_date | 4 | drupal_mm_stg.tn.nid | 1 | |
| 1 | SIMPLE | n | eq_ref | PRIMARY,node_status_type | PRIMARY | 4 | drupal_mm_stg.ma.nid | 1 | Using where |
+----+-------------+-------+--------+--------------------------+-----------------+---------+----------------------+-------+---------------------------------+
字段n.nid, ca.nid, ma.field_article_date_format_value 都被索引了。使用 ORDER BY 子句查询 Limit 0,11 的数据库大约需要 7-10 秒,但如果没有它,查询几乎不需要一秒钟。数据库引擎是MyISAM。对此的任何帮助将不胜感激。
任何可以帮助我像正常查询一样获取此查询的答案(与不按日期排序的查询速度相同)都会很棒。我尝试将复合查询创建为 nid
和 field_article_date_format_value
的组合并在查询中使用并没有帮助解决问题。我愿意提供有关该问题的更多信息和任何新建议。
最佳答案
看看您的查询和解释,似乎在 where 子句中使用 n.status=1 会使搜索效率非常低,因为您需要返回连接定义的整个集合,然后应用状态= 1. 尝试从由 WHERE 立即过滤的 term_node 表开始连接,然后立即使连接添加状态条件。试一试,请告诉我进展如何。
SELECT n.nid, n.title,
ma.field_article_date_format_value,
ma.field_article_summary_value
FROM term_node tn
INNER JOIN node n ON n.nid=tn.nid AND n.status=1
INNER JOIN content_type_article ma FORCE INDEX (ix_article_date) ON n.nid=ma.nid
WHERE tn.tid= 153
ORDER BY ma.field_article_date_format_value DESC
LIMIT 0, 11;
关于mysql - 无法优化使用 ORDER BY 子句的 MySQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13851296/