繁体   English   中英

我怎样才能加快这个连接表本身的查询?

[英]How can I speed up this query that joins a table on itself?

我们有一个“用户”表,用于保存有关我们用户的信息。 此表中的字段之一称为“查询”。 我正在尝试选择具有相同查询的所有用户的用户 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。有什么我可以做的来加速这个查询吗? 我的“<>”比较是否在 join 不好的做法中? 此外,id 字段是主键

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

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

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

CREATE INDEX index_1  ON users (query);

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

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

对于此查询,对哈希索引query可能会更加高性能的(因为它会涉及短得多的比较,在计算哈希值,并使用该指数是无法排序记录的费用):

ALTER TABLE users ADD INDEX (query) USING HASH

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM