如何使具有多个联合的 SQL 更快以实现高速

Posted

技术标签:

【中文标题】如何使具有多个联合的 SQL 更快以实现高速【英文标题】:how to make SQL having many union faster for high speed 【发布时间】:2018-12-03 08:43:28 【问题描述】:

我有一个查询需要很长时间来选择数据。让我分享一下我的数据架构,你对高速而不是我的 SQL 有什么想法吗?

---------------------------------------------------
time                | statA | statB | statC | ... |
---------------------------------------------------
2018-01-01 00:00:00 |   1   |   2   |   1   | ... | 
---------------------------------------------------
2018-01-01 00:00:01 |   2   |   3   |   5   | ... |
---------------------------------------------------
2018-01-01 00:00:02 |   1   |   4   |   3   | ... |
---------------------------------------------------
...

我希望使用查询得到的结果如下:

---------------------------------------
time                |  stat  |  value  |
---------------------------------------
2018-01-01 00:00:00 | statA  |    1    |
---------------------------------------
2018-01-01 00:00:01 | statA  |    2    |
---------------------------------------
2018-01-01 00:00:02 | statA  |    1    |
---------------------------------------
...
...
---------------------------------------
time                |  stat  |  value  |
---------------------------------------
2018-01-01 00:00:00 | statB  |    2    |
---------------------------------------
2018-01-01 00:00:01 | statB  |    3    |
---------------------------------------
2018-01-01 00:00:02 | statB  |    4    |
---------------------------------------
...
...

所以,我的查询现在是

(select time, statA as stat, statA as value
from table)
union (
select time, statB as stat, stastB as value
from table)
union (
select time, statC as stat, stastC as value
from table)

其实,我觉得自己很笨,因为我必须重复编写相同的 SQL,只是 stat id 不同。

有什么建议和方法来开发我的 SQL 吗?

【问题讨论】:

改为使用UNION ALL。否则没关系。 你的桌子设计不是很好。能改吗? @jarlh 除了使用 UNION 和 UNION ALL,还有什么更好的方法吗?不管怎样,让我来做吧。 您使用的是哪个 dbms? 您已经用 UNPIVOT 标记了您的问题,那么为什么不使用它呢? oracle-base.com/articles/11g/… 【参考方案1】:

您可以按照@ibre5041 的建议使用 UNPIVOT

CREATE TABLE table_ (
  time_ DATE, 
  statA NUMBER, 
  statB NUMBER, 
  statC NUMBER
);

INSERT INTO table_ VALUES (TRUNC(SYSDATE)+ 1/24/60/60*0, 1, 2, 1);
INSERT INTO table_ VALUES (TRUNC(SYSDATE)+ 1/24/60/60*1, 2, 3, 5);
INSERT INTO table_ VALUES (TRUNC(SYSDATE)+ 1/24/60/60*2, 1, 4, 3);

COMMIT;


SELECT TO_CHAR(time_, 'YYYY-MM-DD hh24:mi:ss'), stat, value_
FROM   table_
UNPIVOT (value_ FOR stat IN (statA AS 'statA', statB AS 'statB', statC AS 'statC'))
ORDER BY time_;

【讨论】:

它完全有效,还有一个给 ppl 的提示:在 unpivot 之后应该放在哪里。谢谢。【参考方案2】:

有时可以使用 UNION ALL 解决 UNION 的性能问题。

不同之处在于 UNION 过滤掉重复项,而 UNION ALL 没有(性能提升来自不必创建工作表来过滤掉重复项)。

【讨论】:

我仍然需要联合,所以我将 union 替换为 union all【参考方案3】:

unpivot 或横向连接是最好的方法。但是,使用union all 而不是union,您的方法会更快:

select time, statA as stat, statA as value
from table
union all
select time, statB as stat, stastB as value
from table
union all
select time, statC as stat, stastC as value
from table;

union 会产生删除重复项的开销。这个版本仍然需要扫描表 3 次,但重复删除的成本可能要高得多。

【讨论】:

我也打算稍后加入。我已经尝试了其他方法!谢谢

以上是关于如何使具有多个联合的 SQL 更快以实现高速的主要内容,如果未能解决你的问题,请参考以下文章

如何创建作为多个查询联合的 Django 模型字段,以实现覆盖字段?

具有三个未索引联合表和左连接的 MySQL 查询使数据库负担过重

SQL Server中具有不同列数的多个查询的联合结果

SQL联合子句优化

如何使这个 SQL 函数更快?

如何更改 SQL 脚本以使具有金额的列右对齐