Làm thế nào để có được áp dụng chéo để vận hành từng hàng trên một khung nhìn?


7

Chúng tôi có chế độ xem được tối ưu hóa cho các truy vấn mục đơn (200ms không song song):

select * 
    from OptimizedForSingleObjectIdView e2i
   where ObjectId = 3374700

Nó cũng hoạt động trên các tập hợp nhỏ id tĩnh (~ 5).

select * 
    from OptimizedForSingleObjectIdView e2i
   where ObjectId in (3374700, 3374710, 3374720, 3374730, 3374740);

Tuy nhiên, nếu các đối tượng đến từ một nguồn bên ngoài, thì nó tạo ra một kế hoạch chậm. Kế hoạch thực hiện cho thấy nhánh thực thi cho phần khung nhìn đang bỏ qua biến vị ngữ trên ObjectId trong khi trong trường hợp ban đầu, nó sử dụng chúng để thực hiện tìm kiếm chỉ mục.

select v.*
  from 
     (
       select top 1 ObjectId from Objects
        where ObjectId % 10 = 0
        order by ObjectId
     ) o  
  join OptimizedForSingleObjectIdView v -- (also tried inner loop join)
    on v.ObjectId = o.ObjectId;

Chúng tôi không muốn đầu tư vào "kép" tối ưu hóa quan điểm cho các trường hợp không đơn lẻ. Thay vào đó, giải pháp mà chúng tôi "tìm kiếm" là gọi lặp lại chế độ xem một lần cho mỗi đối tượng mà không cần dùng đến SP .

Hầu hết thời gian giải pháp sau đây gọi hàng xem theo hàng. Tuy nhiên không phải lúc này và thậm chí không chỉ cho 1 đối tượng:

select v.*
  from
     (
       select top 1 ObjectId 
         from Objects 
        where ObjectId % 10 = 0 -- non-trivial predicate
        order by ObjectId
     ) o
   cross apply
    (
      select top 2000000000 *
        from OptimizedForSingleObjectIdView v_
       where ObjectId = o.ObjectId 
       order by v_.SomeField
    ) v;

Đã có lúc tôi nghĩ rằng có một tuyên bố rằng việc áp dụng chéo được đảm bảo cho việc thực hiện theo hàng khi nó gọi UDF nhưng điều này cũng thất bại:

create function FunctionCallingView(@pObjectId bigint)
returns table
as 
return select *
  from OptimizedForSingleObjectIdView 
 where ObjectId = @pObjectId;             

select v.*
  from
     (
       select top 1 ObjectId 
         from Objects 
        where ObjectId % 10 = 0
        order by ObjectId
     ) o
 cross apply FunctionCallingView(o.ObjectId) v

Thêm tùy chọn (thứ tự lực lượng) không giúp ích - tuy nhiên đã có hai gợi ý băm trong chế độ xem. Tạm thời loại bỏ chúng không giúp ích và làm chậm trường hợp duy nhất.

Dưới đây là một đoạn của kế hoạch ước tính cho trường hợp chậm dựa trên chức năng. Ước tính của 1 hàng là chính xác. Xa xa về bên phải (không hiển thị) là nơi có một vị từ tìm kiếm không bao gồm kết quả top 1 đó. Điều này có vẻ tương tự như các trường hợp khác mà chúng ta có trong đó các giá trị thăm dò số ít từ các tìm kiếm bảng không được sử dụng như các vị từ tìm kiếm ở nơi khác.

nhập mô tả hình ảnh ở đây


Điều gì xảy ra nếu bạn sử dụng một OPTION(FAST 1)gợi ý?
Erik Darling

@ErikDarling không thay đổi afaict.
crokusek

Geez, tôi đã hỏi câu hỏi gần như tương tự vào năm 2012. Đóng cửa trừ khi có ai có thông tin mới. Kết thúc chế độ xem bằng UDF đa câu lệnh sẽ hoạt động mặc dù nó có cú pháp nặng do chế độ xem cần được xác định. Tất nhiên điều đó sẽ ngăn chặn sự song song trong năm 2012.
crokusek

Câu trả lời:


10

Không thể đảm bảo hoàn toàn việc đánh giá chế độ xem trên mỗi hàng của truy vấn bên ngoài, mà không sử dụng thứ gì đó giới thiệu phạm vi thực thi T-SQL mới, ví dụ: BEGIN...ENDhàm có giá trị bảng không đa dòng (đa câu lệnh ). Đây là khá nhiều lời khuyên được đưa ra để trả lời cho câu hỏi trước của bạn Cách sử dụng gợi ý hợp nhất để cô lập các truy vấn phức tạp trong SQL Server .

Đã có lúc tôi nghĩ rằng có một tuyên bố rằng việc áp dụng chéo được đảm bảo cho việc thực hiện theo hàng khi nó gọi UDF

Điều này không áp dụng cho các hàm có giá trị bảng nội tuyến , vì định nghĩa được mở rộng thành truy vấn gọi trước khi bắt đầu tối ưu hóa.


Điều đó nói rằng, có một số điều bạn có thể làm để khuyến khích mạnh mẽ kết quả mong muốn.

Kế hoạch thực hiện cho thấy nhánh thực thi cho phần khung nhìn đang bỏ qua biến vị ngữ ObjectIdtrong khi trong trường hợp ban đầu, nó sử dụng chúng để thực hiện tìm kiếm chỉ mục.

Bạn đang mong đợi các ObjectIdgiá trị được đánh giá "bên trong chế độ xem" bằng cách sử dụng chỉ mục tìm kiếm cho mỗi hàng lái xe. Đây là kiểu thực hiện các vòng lặp lồng nhau tương ứng (áp dụng). Lưu ý rằng việc sử dụng APPLYphần tử ngôn ngữ T-SQL không đảm bảo rằng việc thực thi vật lý sẽ sử dụng kiểu áp dụng.

Nó nghe có vẻ rất giống như SQL Server đang chọn thực thi với các ObjectIdgiá trị được kiểm tra tại toán tử Nested Loops Join . Đây là một vòng lặp không tương quan, hoặc ngây thơ, lồng nhau tham gia mô hình thực thi.

Rất có thể, điều này được gây ra bởi các gợi ý tham gia mà bạn đang sử dụng bên trong chế độ xem. Các gợi ý tham gia thường được tránh, bởi vì chúng hạn chế rất nhiều quyền tự do tối ưu hóa, và không chỉ đối với kiểu tham gia vật lý. Đặc biệt, tham gia gợi ý cũng buộc thứ tự tham gia cho toàn bộ truy vấn (giống như bạn đã sử dụng một FORCE ORDERgợi ý) và ngăn chặn một số tối ưu hóa liên quan đến vị trí và chiến lược tổng hợp, và nhiều thứ khác bên cạnh đó.

Nếu bạn thực sự phải có các gợi ý tham gia trong chế độ xem (một điều tôi đặc biệt khuyên bạn nên tránh nói chung), bạn có thể tìm thấy cách đáng tin cậy nhất để có được hình dạng kế hoạch mà bạn mong muốn là:

  1. Tạo một hàm inline ( RETURNS TABLE) bằng cách sử dụng định nghĩa khung nhìn (không tham chiếu khung nhìn).
  2. Cung cấp @ObjectIdnhư là một tham số cho chức năng.
  3. Đặt một vị từ bằng cách sử dụng tham số trong thân hàm theo cách làm cho chỉ mục tìm kiếm nhiều khả năng hơn.
  4. Một FORCESEEKgợi ý bảng bên trong hàm có thể được sử dụng nếu thực sự mỗi lần sử dụng sẽ dẫn đến việc tìm kiếm.
  5. Gọi hàm nội tuyến mới bằng cách sử dụng APPLY.

Tôi thường không thích sử dụng các cú pháp và gợi ý cụ thể trong một nỗ lực để buộc một hình dạng kế hoạch vật lý nhất định. Bạn có thể có thành công chung hơn bằng cách tham số hóa các truy vấn và đảm bảo hình dạng kế hoạch bằng hướng dẫn kế hoạch.


Làm cho nó hoạt động bằng cách sử dụng (1,2,3) tuy nhiên việc đặt vị từ ở cuối định nghĩa khung nhìn bên trong ITVF không hoạt động với ứng dụng chéo mặc dù nó hoạt động độc lập khi gọi IVTF thông qua ObjectId theo nghĩa đen. Với các gợi ý băm trước bị loại bỏ, nó vẫn thất bại trong mọi trường hợp. Ân sủng tiết kiệm là ITVF cho phép chuyển động cú pháp của vị từ lên sớm hơn trong chuỗi. Muốn có một gợi ý áp dụng chéo "cứng nhắc".
crokusek

Một hướng dẫn kế hoạch có thể được sử dụng để chỉ định hình một phần cụ thể của kế hoạch cho phép phần còn lại phát triển hoặc nó khóa toàn bộ kế hoạch? Ấn tượng ban đầu của tôi về việc sử dụng PG qua một vài gợi ý rắc rắc là (1) thời gian thiết lập ban đầu và (2) trở ngại kỹ thuật cần thiết cho nhà phát triển tiếp theo để duy trì. Có vẻ như thay đổi quan điểm xuống đường sẽ tạo lại kế hoạch và phân tích, v.v? Mối tương quan trừu tượng giữa cú pháp và thực thi là tốt đẹp cho đến khi không thể tránh khỏi một gợi ý. Nhưng sau khi cú pháp được khóa vào kế hoạch (sau khi sắp xếp lại), một lợi thế sẽ tiếp tục.
crokusek

Để hoàn thành vòng lặp, một khung nhìn đã được tạo để tham gia tất cả các ObjectIds có thể và áp dụng chúng cho ITVF. Bây giờ, chế độ xem mới này dường như được cắm và phát ở bất cứ đâu dưới dạng tham gia mặc định, không cần áp dụng chéo.
crokusek

1
"chuyển động cú pháp của vị ngữ" chính xác là gợi ý của tôi. Tôi thực sự không thể nhận xét về những thứ khác bởi vì nó phụ thuộc vào chi tiết mà bạn chỉ có thể nhìn thấy vào thời điểm này. Nếu bạn muốn biết thêm chi tiết, hãy cung cấp thêm một số chi tiết trong câu hỏi của bạn và tôi sẽ xem xét lại. Hướng dẫn kế hoạch áp dụng cho toàn bộ một tuyên bố.
Paul White 9
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.