首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MySQL + Drupal:在内部联接中忽略索引

MySQL + Drupal:在内部联接中忽略索引
EN

Stack Overflow用户
提问于 2009-05-18 20:14:46
回答 3查看 1.5K关注 0票数 0

我们的环境: Drupal+MySQL

检查查询日志表明,源自Drupal core的node_load函数的以下查询花费了相当多的时间。

对node_load查询的解释表明,USER表上没有使用该索引。

代码语言:javascript
运行
复制
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在这个查询上使用索引?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-05-18 21: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子句)涉及运行一个将影响系统中的每个用户的查询,并且只会随着用户的增加而变得更加繁重。

票数 3
EN

Stack Overflow用户

发布于 2009-05-18 21:58:27

由于MySQL在每个查询中只能为每个表使用一个索引,因此您有时可以通过抛出这个看似无用的条件来获得“自由”范围索引扫描。

代码语言:javascript
运行
复制
WHERE u.uid > 0

尝试在中添加该子句,可能所有表扫描将更改为“范围”,这比全表扫描更好。

票数 1
EN

Stack Overflow用户

发布于 2009-10-04 02:27:22

这会有帮助吗?

在表节点中,在(uid,vid) ALTER TABLE 'xyz_node‘ADD INDEX user_ver ( 'uid,'vid’)上创建索引(注意explain输出中的第二行。在标题“可能的关键字”下..您可以看到vid、uid )

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/879576

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档