该查询很慢(约1.5秒)。它应该只返回一个帖子列表
SELECT SQL_NO_CACHE p.id FROM 1_posts p LEFT JOIN 1_topics t ON (p.cid = t.cid AND p.container = t.id) WHERE t.cid = 1010699;
EXPLAIN给出:
+----+-------------+-------+------+-----------------------+-----------+---------+---------------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+-----------------------+-----------+---------+---------------+------+--------------------------+ | 1 | SIMPLE | t | ref | PRIMARY,cid | cid | 4 | const | 216 | Using where; Using index | | 1 | SIMPLE | p | ref | PRIMARY,cid,container | container | 4 | forumdb.t.id | 49 | Using where | +----+-------------+-------+------+-----------------------+-----------+---------+---------------+------+--------------------------+
请注意,SQL_NO_CACHE仅用于测试目的。
表格的部分结构:
1_posts:
mysql> explain 1_posts; +----------------+----------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------------+----------------------+------+-----+---------+----------------+ | cid | int(20) unsigned | NO | PRI | 0 | | | id | int(20) unsigned | NO | PRI | NULL | auto_increment | | container | int(20) unsigned | NO | MUL | 0 | |
mysql> explain 1_topics; +-----------------+----------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------------+----------------------+------+-----+---------+----------------+ | cid | int(10) unsigned | NO | PRI | 0 | | | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | container | int(20) | NO | MUL | 0 | |
表帖子有数百万条目,主题大约为500k。
两个表上的cid和id都是主要的组合键。 cid表示社区ID。这些表主持许多不同的论坛。
感谢您提供任何帮助,以加快这一点。
答案 0 :(得分:1)
在多个字段(使用AND)上加入时,有助于在这些字段上创建复合索引。
在您的情况下,您可以将帖子中的cid
索引更改为(cid, container)
,这样mysql就可以直接查找行(您仍可以将其用于仅{{1}的查询条件)。
另外你应该把它变成一个INNER JOIN(正如@AndrewK所说),以提高可读性。
答案 1 :(得分:0)
只需查看您的查询,您就可以简化它。
由于您将设置减少到t.cid = 1010699,因此您声明它不能为空。所以你可以使用内连接。
SELECT SQL_NO_CACHE p.id
FROM 1_posts p
JOIN 1_topics t ON p.container = t.id
WHERE t.cid = 1010699 AND p.cid = t.cid;
编辑:
正如Vatev所指出的,删除p.cid = t.cid确实会改变查询结果。为了便于阅读,我在WHERE子句中添加了它