如何使具有多个联合的 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 模型字段,以实现覆盖字段?