Mysql 自联接性能

Posted

技术标签:

【中文标题】Mysql 自联接性能【英文标题】:Mysql Self-Join Performance 【发布时间】:2012-02-23 18:56:17 【问题描述】:

假设我有一个如下所示的表格:

+----+----------+------------+-------+------+
| id | category |      state | A1code| val  |
+----+----------+------------+-------+------+
|  1 |        1 |    Florida | 13000 | 12   |
|  2 |        1 |    Florida | 13001 | 14   |
|  3 |        1 |    Florida | 13002 | 15   |
|  4 |        2 |    Florida | 13000 | 12   |
|  5 |        2 |    Florida | 13001 | 17   |
|  6 |        2 |    Florida | 13002 | 16   |
|  7 |        1 |  Calfornia | 13000 | 15   |
|  8 |        1 |  Calfornia | 13001 | 13   |
|  9 |        1 |  Calfornia | 13002 | 14   |
| 10 |        2 |  Calfornia | 13000 | 12   |
| 11 |        2 |  Calfornia | 13001 | 14   |
| 12 |        2 |  Calfornia | 13002 | 16   |
....
+----+----------+------------+------+

我需要以这种方式得到结果:

state, A1code, category1, category2
Florida,13000, 12,12
Florida,13001, 14,17
Florida,13002, 15,16
Calfornia,13000, 15,12
Calfornia,13001, 13,14
Calfornia,13002, 14,16
....

我目前看到这样的 sql:

SELECT A.STATE, A.A1CODE, A.val AS category1, B.val AS category 2
FROM DUMMY_TABLE A
INNER JOIN DUMMY_TABLE B
USING (STATE,A1CODE)
WHERE A.category = 1 AND B.category = 2;

对于大约 60k 长的表,此查询需要大约 40 秒才能在计算机上运行。

现在有一个类似的查询

SELECT A.STATE, A.A1CODE, A.val AS category1
FROM DUMMY_TABLE A
WHERE A.category = 1

运行时间小于 0.1 秒,而我想要的只是结合两个类别的结果,必须有更快的方法来做到这一点吗?

(当我尝试将数据库从 MS ACCESS 移植到 mysql 时出现此问题。在 MYSQL 上花费约 40 秒的相同查询需要约 1 秒才能在 MS ACCESS 中运行。)

提前致谢

【问题讨论】:

介意再解释一下吗?叫我笨,但我看不到如何在这里有效地应用索引 您是否定义了任何索引?如果没有,你可能需要一些。 我将自动增量“id”列为 btree 索引,但仅此而已... 【参考方案1】:

尝试以下变体

  SELECT A.STATE, A.A1CODE, A.val AS category1, B.val AS category 2
    FROM (select A.STATE A.A1code, A.val as category1 from DUMMY_TABLE A  where A.category = 1 ) as A
    LEFT JOIN DUMMY_TABLE B
    USING (STATE,A1CODE)
    WHERE B.category = 2  ;

它必须快得多。

但实际上这取决于 1)您在第一个查询中有多少列 2)您是否在 A1CODE、STATE 上有索引。

所以要加快速度尝试

create index DUMMY_TABLE_get on DUMMY_TABLE(A1CODE,STATE);

还有一些方法可以将此查询加速到 10-100 毫秒,但它们需要添加额外的字段/触发器。所以如果你不打算每分钟都得到那个查询,那就没有意义了。

请注意,即使是您的请求,40 秒也太长了。可能您已经聘请了 mysql 管理员来调整您的 mysql 服务器(使用更多 RAM 进行连接,增加 keybuffer 等)

【讨论】:

以上是关于Mysql 自联接性能的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 自联接表 Next/Prev 行性能

Oracle DB 使用连接显示多个表中的数据

自联接的困难 MySQL 更新查询

SQLAlchemy:在 MySQL 上使用自联接创建删除查询

查看在表上具有自联接

忽略单峰的内部联接