交叉应用不高效,转换为 unpivot(或其他)?

Posted

技术标签:

【中文标题】交叉应用不高效,转换为 unpivot(或其他)?【英文标题】:Cross apply not performant, convert to unpivot (or other)? 【发布时间】:2017-08-19 09:16:36 【问题描述】:

插入大型数据集时交叉应用非常慢,我认为 unpivot(或其他)可能更有效,但除了使用交叉应用之外,我不知道如何做到这一点:

CREATE TABLE LocData
    (Airport varchar(5), City varchar(5), Country varchar(5))
;

INSERT INTO LocData
    (Airport, City, Country)
VALUES
    ('LHR','LON','GB'),
    ('LGW','LON','GB'),
    ('LCY','LON','US'),
    ('JFK','NYC','US'),
    ('LGA','NYC','US'),
    ('EWR','NYC','US')
;

CREATE TABLE Travel
    (ID int, Dep varchar(5), Arr varchar(5))
;

INSERT INTO Travel
    (ID, Dep, Arr)
VALUES
    (1, 'LHR','JFK'),
    (2, 'LHR','EWR'),
    (3, 'LGA','LGW'),
    (4, 'LCY','EWR')
;

--查询

select * from Travel;

select 
    c.*
    from Travel t
    join LocData dep on dep.Airport=t.Dep
    join LocData arr on arr.Airport=t.Arr
    cross apply
    (
    values 
    (t.ID, dep.Airport, 0, arr.Airport, 0),
    (t.ID, dep.City, 1, arr.City, 1),
    (t.ID, dep.Country, 2, arr.Country, 2)
    ) c (ID, Dep, DepType, Arr, ArrType);

你可以test it here (SQLFiddle)

【问题讨论】:

我只是想写一些粗鲁的东西,因为你的问题看起来非常糟糕,但后来我看到了小提琴链接......我在问题中输入了代码,这肯定会带给你更好的答案... 是否有任何索引/外键?您真的使用 3-char 机场代码作为 FK 吗? 非常慢是什么意思,什么是大型数据集 谢谢@Shnugo 不确定我是否应该同时提供,以后会这样做。 【参考方案1】:

您的查询是:

select c.*
from Travel t join
     LocData dep
     on dep.Airport = t.Dep join
     LocData arr
     on arr.Airport = t.Arr cross apply
     (values (t.ID, dep.Airport, 0, arr.Airport, 0),
             (t.ID, dep.City, 1, arr.City, 1),
             (t.ID, dep.Country, 2, arr.Country, 2)
    ) c(ID, Dep, DepType, Arr, ArrType);

这似乎是一种非常有效的方式来做你想做的事。它应该有很好的性能。

可以提高性能的一件事是在Locadata(airport) 上建立索引。您还可以包含citycountry 列(include 或者使它们成为附加键)。我会使用它作为主键来定义表(它会自动创建最佳类型的索引):

CREATE TABLE LocData (
    Airport varchar(5) PRIMARY KEY,
    City varchar(5),
    Country varchar(5)
);

(合理假设它永远不会是NULL 并且永远不会重复。)

换句话说,我真诚地怀疑apply 会影响性能。 joins 更有可能是罪魁祸首。

【讨论】:

你是对的,这个问题与交叉申请无关,它取决于我在此处发布的进一步操作。现在在 40 秒内插入 3mil+(之前是 19 分钟)。快乐的日子,虚惊一场。

以上是关于交叉应用不高效,转换为 unpivot(或其他)?的主要内容,如果未能解决你的问题,请参考以下文章

交叉应用与 UNPIVOT

SQL Unpivot、交叉应用、动态查询?

在 MongoDB 或其他 DB 中存储 100Mb 文件和高效的交叉连接操作

如何在主查询中编写 Unpivot 查询?

如何在SQL中产生交叉式数据表(枢纽分析表)Part 2(PIVOT,UNPIVOT)

如何在 Sql Server 2008 R2 中将列转换为行?