首页 文章

MySQL:跨表优化连接

提问于
浏览
1

该查询很慢(大约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 . 这些表包含许多不同的论坛 .

感谢您提供任何帮助,以加快这一点 .

2 回答

  • 0

    在多个字段上加入(使用AND)时,有助于在这些字段上创建复合索引 .

    在您的情况下,您可以将帖子中的 cid 索引更改为 (cid, container) ,这样mysql将能够直接查找行(您仍然可以将其用于仅具有 cid 条件的查询) .

    另外你应该把它变成INNER JOIN(如@AndrewK所说),以提高可读性 .

  • 1

    只需查看您的查询,您就可以简化它 .

    由于您将设置减少到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子句中添加了它

相关问题