Cần trợ giúp về chỉ mục / hiệu suất của SQL Server (quét chỉ mục và sắp xếp mất 40 phút)


7

Cuối cùng tôi đã tìm ra logic cho một truy vấn, bây giờ tôi cần tăng tốc nó lên ... đáng kể, nếu có thể (nó chạy trong 40 phút +/-). Nó nằm trên hai cái bàn, một cái chỉ có vài trăm hàng ( tblTradingDays) và cái kia có hơn một triệu ( tblDailySMA). Nó trả về 48 triệu hàng.

Logic cơ bản của tôi là: Tôi trả về một hàng cho mỗi kết hợp ký hiệu, ngày giao dịch và giá trị thời gian, tạo ra một cặp giai đoạn "chậm v nhanh". Vì vậy, trong bảng gốc, có một biểu tượng, ngày giao dịch, khoảng thời gian (5,10,20, ...) và giá trị thực tế cho sự kết hợp đó. Tôi muốn so sánh các giá trị cho tất cả các kết hợp của các khoảng thời gian (ngoại trừ khoảng thời gian p1 = thời gian p2). Tôi đang đánh số các hồ sơ sẽ được sử dụng để xử lý thêm. Hy vọng rằng có ý nghĩa.

Tôi đã thử các chỉ mục và kết hợp khác nhau của các lĩnh vực liên quan đến các phép nối và vị từ. Trong kế hoạch thực hiện ước tính, có vẻ như một loại là hoạt động tốn kém nhất. Chỉ mục duy nhất tblDailySMAxuất hiện trong kế hoạch, mặc dù tôi thêm những người khác là không Symbol, TradeDate, Periodbao gồm , duy nhất, trên : , và bao gồm Value. Nó được quét. Các truy vấn dưới đây, hy vọng ai đó có thể giúp tôi ra. Cảm ơn trước..

SELECT 
   ROW_NUMBER() OVER 
   (
        ORDER BY t1.Symbol, t1.Period, t2.Period, t.TradingDate DESC
   ) RowNum,
   t1.Symbol, t.TradingDate, t1.Period, t2.Period, t1.Value FastValue, 
   t2.Value SlowValue, (t1.Value - t2.Value) SlowFastDiff,
   ChgSign = CASE WHEN t1.Value < t2.Value THEN 0 
                  WHEN t1.Value >= t2.Value THEN 1 
                  WHEN t1.Value IS NULL OR t2.Value IS NULL THEN NULL 
             END
FROM 
    tblTradingDays t 
RIGHT JOIN 
    tblDailySMA t1 ON t.TradingDate = t1.TradeDate
INNER JOIN 
    tblDailySMA t2 ON t1.Symbol = t2.Symbol AND t1.TradeDate  = t2.TradeDate
WHERE 
    t1.Period < t2.Period

Đây là kế hoạch thực hiện:

  |--Compute Scalar(DEFINE:([Expr1007]=[Market].[dbo].[tblDailySMA].[Value] as [t1].[Value]-[Market].[dbo].[tblDailySMA].[Value] as [t2].[Value], [Expr1008]=CASE WHEN [Market].[dbo].[tblDailySMA].[Value] as [t1].[Value]<[Market].[dbo].[tblDailySMA].[Value] as [t2].[Value] THEN (0) ELSE CASE WHEN [Market].[dbo].[tblDailySMA].[Value] as [t1].[Value]>=[Market].[dbo].[tblDailySMA].[Value] as [t2].[Value] THEN (1) ELSE NULL END END))
       |--Sequence Project(DEFINE:([Expr1006]=row_number))
            |--Segment
                 |--Parallelism(Gather Streams, ORDER BY:([t1].[Symbol] ASC, [t1].[Period] ASC, [t2].[Period] ASC, [t].[TradingDate] DESC))
                      |--Sort(ORDER BY:([t1].[Symbol] ASC, [t1].[Period] ASC, [t2].[Period] ASC, [t].[TradingDate] DESC))
                           |--Hash Match(Right Outer Join, HASH:([t].[TradingDate])=([t1].[TradeDate]), RESIDUAL:([Market].[dbo].[tblTradingDays].[TradingDate] as [t].[TradingDate]=[Market].[dbo].[tblDailySMA].[TradeDate] as [t1].[TradeDate]))
                                |--Parallelism(Distribute Streams, Hash Partitioning, PARTITION COLUMNS:([t].[TradingDate]))
                                |    |--Index Scan(OBJECT:([Market].[dbo].[tblTradingDays].[PK_tblTradingDays] AS [t]))
                                |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([t1].[TradeDate]))
                                     |--Merge Join(Inner Join, MANY-TO-MANY MERGE:([t1].[Symbol], [t1].[TradeDate])=([t2].[Symbol], [t2].[TradeDate]), RESIDUAL:([Market].[dbo].[tblDailySMA].[Symbol] as [t1].[Symbol]=[Market].[dbo].[tblDailySMA].[Symbol] as [t2].[Symbol] AND [Market].[dbo].[tblDailySMA].[TradeDate] as [t1].[TradeDate]=[Market].[dbo].[tblDailySMA].[TradeDate] as [t2].[TradeDate] AND [Market].[dbo].[tblDailySMA].[Period] as [t1].[Period]<[Market].[dbo].[tblDailySMA].[Period] as [t2].[Period]))
                                          |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([t1].[Symbol], [t1].[TradeDate]), ORDER BY:([t1].[Symbol] ASC, [t1].[TradeDate] ASC))
                                          |    |--Index Scan(OBJECT:([Market].[dbo].[tblDailySMA].[IX_tblDailySMA_Noncl_SymbTrDatePer] AS [t1]), ORDERED FORWARD)
                                          |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([t2].[Symbol], [t2].[TradeDate]), ORDER BY:([t2].[Symbol] ASC, [t2].[TradeDate] ASC))
                                               |--Index Scan(OBJECT:([Market].[dbo].[tblDailySMA].[IX_tblDailySMA_Noncl_SymbTrDatePer] AS [t2]), ORDERED FORWARD)

Bạn có thể gửi kế hoạch thực hiện của bạn?
mwigdahl

Bạn cũng có thể giải thích những gì bạn đang cố gắng làm. Cấu trúc bạn có ở đây là một phép nối tam giác, không có quy mô tốt với tất cả các bảng lớn.
mwigdahl

Bạn bắt đầu với bảng lớn nhất, sau đó nối các bảng nhỏ hơn với nó.
Kermit

Bạn cần tblTradingDaysgì? Hình như nó không làm gì cả. Hoặc có thể bạn muốn LEFT JOINthay vì RIGHT JOIN?

@YuxiuLi Bắt tốt, tôi chỉ sửa rằng ... dữ liệu trong tblDailySMA bị thiếu một vài giá trị, vì vậy tôi sử dụng nối ngoài bên trái để giữ nghiêm ngặt.

Câu trả lời:


3

Khi tôi gặp loại vấn đề về hiệu năng này trong một truy vấn lớn, tôi chia nó thành các truy vấn nhỏ với các bảng tạm thời. Đối với tôi đó là một giải pháp và tỷ lệ hiệu suất có thể là 10 đến 1 hoặc nhiều hơn.

Bước đầu tiên:

with t1 as (
SELECT 
  t1.Symbol, 
  t1.Period, 
  t.TradingDate,
  t1.Value as FastValue
FROM      tblDailySMA t1 
LEFT JOIN tblTradingDays t 
        ON t.TradingDate = t1.TradeDate
) 
select * 
into #t1
from t1;

--I include period into idex to avoid table access on next query
create index t1_idx on ( Symbol, TradeDate, Period ) 

Bước Secon:

with t2 as (
SELECT
  t1.Symbol, 
  t1.Period as period_t1, 
  t.TradingDate,
  t1.Value as FastValue
  t2.Period as period_t2,
  t2.Value as SlowValue,
  t2.TradeDate
FROM       #t1 as t1
INNER JOIN tblDailySMA t2 
   ON t1.Symbol = t2.Symbol AND t1.TradeDate  = t2.TradeDate
WHERE t1.Period < t2.Period
)
select 
  *
into #t2
from t2;

--Here create indexes for t2
--Here next and final query 

Và như thế. Một lợi ích của hệ thống này là bạn có thể cải thiện các truy vấn từng bước.


Bảng tạm thời có thể dễ dàng tăng tệp nhật ký rất nhanh?
thử nghiệm

@NilishGarg, Cảm ơn về nhận xét của bạn, nhưng, OP không nói về giới hạn lưu trữ. Tại sao bạn cảnh báo chúng tôi về điều này?

Thật ra anh đang nói về 48 triệu hàng. Tôi đã có vấn đề tương tự trước đây. Tôi đã chủ động tương tự (liên quan đến các bảng tạm thời). Nhưng điều này gây ra tình huống tồi tệ nhất. Tại sao? Ổ cứng bắt đầu chiếm dung lượng 22GB trong một tuần do tệp .ldf. Trong biết điều này sẽ khắc phục vấn đề nhưng tạm thời.
thử nghiệm

1
Tôi không sử dụng hoặc dựa vào tệp nhật ký bao giờ .. Tôi thực hiện sao lưu toàn bộ mỗi đêm ..
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.