2

我们有一个“用户”表,其中包含有关我们用户的信息。此表中的一个字段称为“查询”。我正在尝试选择具有相同查询的所有用户的用户 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 |
+----+-------------+-------+-------+----------------------+----------------------+---------+---------------------------------+----------+--------------------------+

正如您从解释中看到的,用户表在查询中被索引,并且该索引似乎正在我的 SELECT 中使用。我想知道为什么表 u2 上的“行”列的值为 11,而不是 1。我可以做些什么来加快这个查询的速度吗?我的 '<>' 在 join 中的比较是不好的做法吗?此外,id 字段是主键

4

4 回答 4

1

查询的主要驱动因素是query字段上的相等性——如果它被索引的话。<> 到 theid可能不是很具体,它通过用于它的选择类型显示为 'ref'

以下仅适用于“查询”未编入索引的情况......

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

CREATE INDEX index_1  ON users (query);

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

于 2012-11-19T19:10:50.840 回答
1

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

对于这个查询,hash index onquery的性能可能要高得多(因为它会涉及更短的比较,代价是计算 hash 并且无法使用该索引对记录进行排序):

ALTER TABLE users ADD INDEX (query) USING HASH

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

于 2012-11-19T19:22:05.333 回答
0

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

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

然后从此表中选择并按 queryId 分组

于 2012-11-19T19:10:50.583 回答
0

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

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

如果你有两个以上的用户有相同的查询,你能解释一下为什么你想要所有这样的用户对吗?

于 2012-11-19T19:21:20.660 回答