質問

これらの詳細の詳細と合計の2つの表があります。

詳細 (ゆっくりとした解決策):

select 
    OrderId             =   r.OrderId                   
  , TotalQty            =   SUM(r.Quantity)
  , TotalGrossConsid    =   SUM(r.Price * r.Quantity)
from dbo.Order r
group by r.OrderId

合計(高速ソリューション):

select 
    t.OrderId                           
  , t.TotalQty          
  , t.TotalGrossConsid  
  , t.IsValid
from dbo.OrderTotal t

合計が無効になることがあります(一部のジョブは、合計の変更を再計算する必要がありますが、遅延します)。理解するにつれて、2番目のクエリはより速く、有効な合計の数は無効なものよりも多くなります。そのため、2番目のテーブル(合計)から有効な合計を返す合計クエリを探しており、最初のスロークエリを使用して動的に再計算された合計を返します。したがって、私の目標は到達します。すべての合計は有効であり、応答するまでの時間は完全な再計算よりも高速です。

これが私の試みです(ハイブリッドソリューション):

with fast_static(OrderId, TotalQty, TotalGrossConsid, IsValid)
as
(
    select 
        t.OrderId                           
      , t.TotalQty          
      , t.TotalGrossConsid  
      , t.IsValid
    from dbo.OrderTotal t
)

, slow_dynamic(OrderId, TotalQty, TotalGrossConsid)
(
   select 
        OrderId             =   r.OrderId                   
      , TotalQty            =   SUM(r.Quantity)
      , TotalGrossConsid    =   SUM(r.Price * r.Quantity)
    from dbo.Order r
)
select
    OrderId, TotalQty, TotalGrossConsid
from fast_static 
where IsValid = 1  
union all
select
  OrderId, TotalQty, TotalGrossConsid 
from slow_dynamic s 
    --inner join fast_static ff
    --on ff.OrderId = s.OrderId 
where   --ff.Valid = 0 -- too slow!!!
    s.OrderId in (select OrderId from fast_static f where f.Valid = 0)

高速ソリューションとハイブリッドソリューションを比較しました。32%から68%(相対クエリコスト)を得ました。コメントされたバリアントを見ることができれば、それは1%から99%に等しくなります(あまりにも悪い)。このクエリを改善することは可能ですか?

追加した

@GBN:

Valid  =  case when i.OrderId is null then 1 else 0 end
...
dbo.OrderTotal t  left join dbo.InvalidOrders i

はい、合計を再計算する仕事があり、このプロセスはクエリリクエストに同期されていません。 InvalIdordersテーブルは、合計が無効であることを知るために記録を保存する小さなものです(再計算される)

解決

インデックス付きビューが最良の選択です。 SQL Server Editionに注意してください(ノーエクスパンドヒント 非植物版のために)そして準備ができています いくつかのデータベースオブジェクトを再作成します (SET ANSI_NULLS ON, SET QUOTED_IDENTIFIER ON)クライアント側でインデックス付きビューの使用を開始します。

役に立ちましたか?

解決

なぜあなたがその場で集約できないのか、なぜそれがそんなに遅いのか理解できません。 「有効な」アイデアは、OrderTotalsまたはいくつかのビジネスプロセスの遅れに対処するための回避策ですか

これらのアイデアはどちらも、索引不良の回避策である無効な注文テーブルを破棄します。

  • 提案1:

計算された列を作成します

ALTER TABLE dbo.Order ADD PriceXQuantity AS Price * Quantity PERSISTED

インデックスを追加します

CREATE INDEX IX_Totals ON dbo.Order (OrderID) INCLUDE Quantity, PriceXQuantity)

何が起こるか見てください

  • 提案2:

インデックス付きビューを使用します

CREATE VIEW OrderTotals
WITH SCHEMABINDING
AS
select 
    OrderId             =   r.OrderId                   
  , TotalQty            =   SUM(r.Quantity)
  , TotalGrossConsid    =   SUM(r.Price * r.Quantity)
  , COUNT_BIG(*) AS Dummy
from dbo.Order r
group by r.OrderId
GO
CREATE UNIQUE CLUSTERED INDEX IXCU_OrderTotals ON OrderTotals (OrderId9
GO

ここでも計算された列も使用できます

他のヒント

コストが高すぎない場合は、移動を検討することができます IsValid にフラグ Detail テーブルとインデックスを作成しますか?これにより、トランザクションが遅くなりますが、(おそらく)大きいようにクエリパフォーマンスを改善します Detail テーブルは1つのビッグでアクセスされます range scan

ライセンス: CC-BY-SA帰属
所属していません dba.stackexchange
scroll top