我们的环境: Drupal+MySQL
检查查询日志表明,源自Drupal core的node_load函数的以下查询花费了相当多的时间。
对node_load查询的解释表明,USER表上没有使用该索引。
mysql> explain SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed,
n.comment, n.promote, n.sticky, r.timestamp AS revision_timestamp, r.title,
r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data
FROM xyz_node n
INNER JOIN xyz_users u ON n.uid = u.uid
INNER JOIN xyz_node_revisions r ON r.vid = n.vid;
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+
| 1 | SIMPLE | u | ALL | PRIMARY | NULL | NULL | NULL | 181 | |
| 1 | SIMPLE | n | ref | vid,uid | uid | 4 | xyz.u.uid | 9 | Using where |
| 1 | SIMPLE | r | eq_ref | PRIMARY | PRIMARY | 4 | xyz.n.vid | 1 | |
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+
你知道这是怎么回事吗,我该如何强制MYSQL在这个查询上使用索引?
发布于 2009-05-18 13:55:15
表的联接顺序不一定与FROM
子句中指定的顺序相同。在本例中,看起来MySQL已经决定在查询中没有WHERE
子句的情况下,首先扫描users表,然后再将其与其他表连接起来可能是最快的。
我要做的第一件事是对查询中涉及的所有三个表运行ANALYZE TABLE
。这将更新表统计信息和存储的键分布,并允许连接优化器做出更好的决策。然后运行EXPLAIN
语句,查看它是否发生了更改。
如果它没有改变,您可能需要求助于使用STRAIGHT_JOIN
关键字。这将强制联接优化器按照查询中指定的确切顺序联接这些表。为了帮助确定是否应该这样做,应该取EXPLAIN
结果中所有rows
值的乘积,并将其与查询返回的实际行数进行比较。因此,在本例中,将1629 (181x9x1)与实际行数进行比较。如果它们明显不同,则可能需要一个STRAIGHT_JOIN
(用作SELECT
的关键字,即.SELECT STRAIGHT_JOIN n.nid
...等)。
顺便说一句,有一种方法可以tell MySQL to use a specific index,但我认为它不适用于这个查询中的user表,因为现在没有WHERE
子句。如果最终使用的是STRAIGHT_JOIN
,则可能需要它,但在这种情况下,如果用户表不是连接中的第一个表,则MySQL可能会选择主键。
您还应该查看EXPLAIN syntax page,了解有关这方面的更多有用的细节。
这个查询看起来并不是很慢。如果没有where子句,您可能会在某个地方进行全表扫描,而MySQL已将检查的总行数减少到大约1700行。这似乎只有当它是一个高使用率的查询时才会有问题,在这种情况下,您可能想要检查底层架构,该架构(没有WHERE
子句)涉及运行一个将影响系统中的每个用户的查询,并且只会随着用户的增加而变得更加繁重。
发布于 2009-05-18 13:58:27
由于MySQL在每个查询中只能为每个表使用一个索引,因此您有时可以通过抛出这个看似无用的条件来获得“自由”范围索引扫描。
WHERE u.uid > 0
尝试在中添加该子句,可能所有表扫描将更改为“范围”,这比全表扫描更好。
发布于 2009-10-03 18:27:22
这会有帮助吗?
在表节点中,在(uid,vid) ALTER TABLE 'xyz_node‘ADD INDEX user_ver
( 'uid,'vid’)上创建索引(注意explain输出中的第二行。在标题“可能的关键字”下..您可以看到vid、uid )
https://stackoverflow.com/questions/879576
复制