Merge之前的SubQuery与TempTable

时间:2013-04-10 14:51:08

标签: sql sql-server tsql optimization

我有一个复杂的查询,我想将其用作合并到表中的源。这将在数​​百万行上执行。目前,我试图通过在合并之前将其插入临时表来对数据应用约束。

操作是:

  • 过滤掉重复的数据。
  • 加入一些表格以获取更多数据
  • 插入临时表。

这是查询。

-- Get all Orders that aren't in the system
WITH Orders AS
(
    SELECT *
    FROM [Staging].Orders o
    WHERE NOT EXISTS
    (
        SELECT 1
        FROM Maps.VendorBOrders vbo
        JOIN OrderFact of
        ON of.Id = vbo.OrderFactId
        AND InternalOrderId = o.InternalOrderId
        AND of.DataSetId = o.DataSetId
        AND of.IsDelete = 0
    )
)
INSERT INTO #VendorBOrders
    (
      CustomerId
     ,OrderId
     ,OrderTypeId
     ,TypeCode
     ,LineNumber
     ,FromDate
     ,ThruDate
     ,LineFromDate
     ,LineThruDate
     ,PlaceOfService
     ,RevenueCode
     ,BillingProviderId
     ,Cost
     ,AdjustmentTypeCode
     ,PaymentDenialCode
     ,EffectiveDate
     ,IDRLoadDate
     ,RelatedOrderId
     ,DataSetId
    )
SELECT
     vc.CustomerId
    ,OrderId
    ,OrderTypeId
    ,TypeCode
    ,LineNumber
    ,FromDate
    ,ThruDate
    ,LineFromDate
    ,LineThruDate
    ,PlaceOfService
    ,RevenueCode
    ,bp.Id
    ,Cost
    ,AdjustmentTypeCode
    ,PaymentDenialCode
    ,EffectiveDate
    ,IDRLoadDate
    ,ro.Id
    ,o.DataSetId
FROM
Orders o
-- Join related orders to match orders sharing same instance
JOIN Maps.VendorBRelatedOrder ro
ON ro.OrderControlNumber = o.OrderControlNumber
AND ro.EquitableCustomerId = o.EquitableCustomerId
AND ro.DataSetId = o.DataSetId
JOIN BillingProvider bp
ON bp.ProviderNPI = o.ProviderNPI
-- Join on customers and fail if the customer doesn't exist
LEFT OUTER JOIN [Maps].VendorBCustomer vc
ON vc.ExtenalCustomerId = o.ExtenalCustomerId
AND vc.VendorId = o.VendorId;

我想知道我能做些什么来优化它的时间。我尝试过使用数据库引擎调优器,但此查询占用的CPU时间比我运行的其他查询多100倍。还有什么我可以研究或者查询不能进一步改进吗?

2 个答案:

答案 0 :(得分:1)

通常,当我进行速度测试时,我会对SQL的各个部分执行检查,以查看问题所在。打开“执行计划”,看看很多时间的去向。此外,如果你想快速和肮脏地突出你的CTE并运行它。是这么快,是的,继续前进。

我有时发现一个单独的索引会抛出整个复杂的连接逻辑,只需让数据库执行大的一部分,然后找到那个部分。

另一个想法是,如果您在生产环境中有快速tempdb等,也可以将CTE转储到临时表中。索引,看看是否加快了速度。有时CTE,表变量和临时表在连接时会失去一些性能。我发现在部分对象上创建索引有时会提高性能,但是你也会在tempdb上加载更多的负载来做到这一点,所以请记住这一点。

答案 1 :(得分:1)

CTE只是语法

在该连接上评估(运行)CTE

首先将它作为select语句运行(无插入)

如果选择慢,则:
将CTE移动到#TEMP,以便对其进行一次评估并实现 在三个连接列上放置一个索引(如果适用,PK)

如果select不慢,那么它就是#VendorBOrders上的插入时间 Fist只创建PK并对PK上的插入进行排序,以便不对该聚簇索引进行分段 然后在插入完成之后构建任何其他必要的索引