如何加快连接表自身的查询?

时间:2012-11-19 18:58:25

标签: mysql

我们有一个“用户”表,其中包含有关我们用户的信息。此表中的一个字段称为“查询”。我试图选择具有相同查询的所有用户的用户ID。所以我的输出应该是这样的:

user1_id    user2_id    common_query
   43          2            "foo"
   117         433          "bar"
   1           119          "baz"
   1           52           "qux"

不幸的是,我无法在一小时内完成此查询(用户表非常大)。这是我目前的查询:

SELECT u1.id,
       u2.id,
       u1.query
FROM users u1
INNER JOIN users u2
        ON u1.query = u2.query
       AND u1.id <> u2.id

我的解释:

+----+-------------+-------+-------+----------------------+----------------------+---------+---------------------------------+----------+--------------------------+
| id | select_type | table | type  | possible_keys        | key                  | key_len | ref                             | rows     | Extra                    |
+----+-------------+-------+-------+----------------------+----------------------+---------+---------------------------------+----------+--------------------------+
|  1 | SIMPLE      | u1    | index | index_users_on_query | index_users_on_query | 768     | NULL                            | 10905267 | Using index              |
|  1 | SIMPLE      | u2    | ref   | index_users_on_query | index_users_on_query | 768     | u1.query                        |       11 | Using where; Using index |
+----+-------------+-------+-------+----------------------+----------------------+---------+---------------------------------+----------+--------------------------+

从解释中可以看出,users表在查询时被索引,索引似乎正在我的SELECT中使用。我想知道为什么表u2上的'rows'列的值为11,而不是1.有什么办法可以加快查询速度吗?是我的'&lt;&gt;'加入不良做法比较?此外,id字段是主键

4 个答案:

答案 0 :(得分:1)

查询的主要驱动因素是query字段上的相等性 - 如果它已编入索引。 &lt;&gt; id的{​​{1}}可能不是非常具体,它显示的选择类型是'ref'

以下仅适用于'query'未编入索引....

如果id是主键,您可以这样做:

CREATE INDEX index_1  ON users (query);

添加此类索引的结果将是查询的覆盖索引,并将导致查询执行速度最快。

答案 1 :(得分:1)

我最关心的是key_len,它表明MySQL必须比较多达768个字节才能查找每个索引条目。

对于此查询,query上的哈希索引可能更具性能(因为它将涉及大大缩短的比较,代价是计算哈希并且无法使用该索引对记录进行排序):

ALTER TABLE users ADD INDEX (query) USING HASH

您也可以考虑在(query, id)上将其设为复合,以便MySQL无需扫描到记录本身来测试<>标准。

答案 2 :(得分:0)

您有多少查询?您可以添加表UsersInQueries:

id   queryId   userId
0      5         453   
1      23        732 
2      15        761

然后从此表中选择并按queryId

分组

答案 3 :(得分:0)

如果每个查询最多只有两个用户,则可以改为:

select query, min(id) as FirstID, max(id) as SecondId
from users
group by query
having count(*) > 1

如果您有两个以上具有相同查询的用户,您能否解释为什么您需要所有这类用户?