1

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

操作是:

  • 过滤掉重复数据。
  • 加入一些表以提取其他数据
  • 插入临时表。

这是查询。

-- 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;

我想知道是否有什么我可以做的来优化它的时间。我曾尝试使用 DB Engine Tuner,但此查询比我正在运行的其他查询多占用 100 倍的 CPU 时间。还有什么我可以研究的,或者查询不能进一步改进吗?

4

2 回答 2

1

通常,当我进行速度测试时,我会检查 SQL 的各个部分以查看问题所在。打开“执行计划”,看看大部分时间都花在了哪里。此外,如果您只想快速而肮脏地突出显示您的 CTE 并运行它。是不是很快,是的,继续前进。

我有时发现一个索引被关闭会抛出整个复杂的连接逻辑,只需让数据库做一些大事情的一部分,然后找到那个部分。

另一个想法是,如果您在生产环境或类似环境中有一个快速的 tempdb,那么也将您的 CTE 转储到一个临时表中。对此进行索引,看看是否可以加快速度。有时 CTE、表变量和临时表在连接时会失去一些性能。我发现在部分对象上创建索引有时会提高性能,但您也会在 tempdb 上增加更多负载来执行此操作,因此请记住这一点。

于 2013-04-10T16:29:07.303 回答
1

CTE 只是语法

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

首先将其作为选择语句运行(不插入)

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

如果选择不慢那么它是#VendorBOrders 上的插入时间
拳头只创建PK并对PK上的插入进行排序,以免对该聚集索引进行碎片化
然后在插入完成后构建任何其他必要的索引

于 2013-04-10T19:17:40.043 回答