我正在使用以下查询来查找我的Drupal站点中前6个已查看的页面:
SELECT n.title, n.nid, c.daycount
FROM node n
JOIN node_counter c ON n.nid=c.nid
WHERE n.type='page' AND n.status = 1
ORDER BY c.daycount DESC
LIMIT 0,6;
这很自然,适用于大多数网站。但是,在具有许多节点(1.7米)的站点上,由于用户在系统中添加/编辑节点,因此节点表不断变化,因此它很慢,并且很难缓存,因为它很难缓存。
在重型站点上运行说明会产生以下输出:
+----+-------------+-------+--------+-----------------------------------------------+------------------+---------+------------------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-----------------------------------------------+------------------+---------+------------------+-------+----------------------------------------------+
| 1 | SIMPLE | n | ref | PRIMARY,node_type,status,node_status_type,nid | node_status_type | 102 | const,const | 71878 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | c | eq_ref | PRIMARY | PRIMARY | 4 | kidstvprd2.n.nid | 1 | Using where |
+----+-------------+-------+--------+-----------------------------------------------+------------------+---------+------------------+-------+----------------------------------------------+
请注意“使用where;使用临时;使用filesort”。
我想到的一个解决方案是离线运行此查询(或许在cron中),并将结果保存在另一个表中供任何人阅读,直到下一个cron运行更新它。但是,在重新转换为cron之前,我想尝试优化此查询。
有人对如何优化它有所了解吗?
由于
答案 0 :(得分:2)
问题在于它是从n表而不是c开始的。你想要的是它在c.daycount上使用索引(以避免排序),然后将它连接到n。如有必要,请使用straight_join强制执行订单。
答案 1 :(得分:0)
在SQLServer中,我会确保有以下索引
CREATE INDEX IX_NODE_NID_TYPE_STATUS_TITLE
ON dbo.Node (Nid, Type, Status) INCLUDE (Title)
CREATE INDEX IX_NODE_COUNTER_NID_DAYCOUNT
ON dbo.Node_Counter (Nid, DayCount)