Thứ tự sắp xếp được chỉ định trong khóa chính, nhưng việc sắp xếp được thực hiện trên CHỌN


15

Tôi đang lưu trữ dữ liệu cảm biến trong bảng SensorValues . Bảng và khóa chính như sau:

CREATE TABLE [dbo].[SensorValues](
  [DeviceId] [int] NOT NULL,
  [SensorId] [int] NOT NULL,
  [SensorValue] [int] NOT NULL,
  [Date] [int] NOT NULL,
CONSTRAINT [PK_SensorValues] PRIMARY KEY CLUSTERED 
(
  [DeviceId] ASC,
  [SensorId] ASC,
  [Date] DESC
) WITH (
    FILLFACTOR=75,
    DATA_COMPRESSION = PAGE,
    PAD_INDEX = OFF,
    STATISTICS_NORECOMPUTE = OFF,
    SORT_IN_TEMPDB = OFF,
    IGNORE_DUP_KEY = OFF,
    ONLINE = OFF,
    ALLOW_ROW_LOCKS = ON,
    ALLOW_PAGE_LOCKS = ON)
  ON [MyPartitioningScheme]([Date])

Tuy nhiên, khi tôi chọn giá trị cảm biến hợp lệ trong một thời gian cụ thể, kế hoạch thực hiện cho tôi biết nó đang thực hiện sắp xếp. Tại sao vậy?

Tôi đã nghĩ rằng vì tôi lưu trữ các giá trị được sắp xếp theo cột Ngày, nên việc sắp xếp sẽ không xảy ra. Hoặc là do chỉ mục không được sắp xếp duy nhất theo cột Ngày, nghĩa là nó không thể cho rằng tập kết quả được sắp xếp?

SELECT TOP 1 SensorValue
  FROM SensorValues
  WHERE SensorId = 53
    AND DeviceId = 3819
    AND Date < 1339225010
  ORDER BY Date DESC

Kế hoạch thực hiện

Chỉnh sửa: Tôi có thể làm điều này thay thế?

Vì bảng được sắp xếp DeviceId, SensorId, Date và tôi thực hiện CHỌN chỉ định một DeviceId và một SensorId , nên bộ đầu ra phải được sắp xếp theo Ngày DESC . Vì vậy, tôi tự hỏi nếu câu hỏi sau đây sẽ mang lại kết quả tương tự trong tất cả các trường hợp?

SELECT TOP 1 SensorValue
  FROM SensorValues
  WHERE SensorId = 53
    AND DeviceId = 3819
    AND Date < 1339225010

Theo @Catcall dưới đây, thứ tự sắp xếp không giống với thứ tự lưu trữ. Tức là chúng ta không thể cho rằng các giá trị được trả về đã được sắp xếp theo thứ tự.

Chỉnh sửa: Tôi đã thử giải pháp CROSS ỨNG DỤNG này, không có may mắn

@Martin Smith đề nghị tôi nên thử RA KHI ỨNG DỤNG kết quả của tôi đối với các phân vùng. Tôi tìm thấy một bài đăng trên blog ( Các chỉ mục không được phân cụm trên bảng được phân vùng ) mô tả vấn đề tương tự này và đã thử giải pháp hơi giống với những gì Smith đề xuất. Tuy nhiên, không có may mắn ở đây, thời gian thực hiện ngang bằng với giải pháp ban đầu của tôi.

WITH Boundaries(boundary_id)
AS
(
  SELECT boundary_id
  FROM sys.partition_functions pf
  JOIN sys.partition_range_values prf ON pf.function_id = prf.function_id
  WHERE pf.name = 'PF'
  AND prf.value <= 1339225010
  UNION ALL
  SELECT max(boundary_id) + 1
  FROM sys.partition_functions pf
  JOIN sys.partition_range_values prf ON pf.function_id = prf.function_id
  WHERE pf.name = 'PF'
  AND prf.value <= 1339225010
),
Top1(SensorValue)
AS
(
  SELECT TOP 1 d.SensorValue
  FROM Boundaries b
  CROSS APPLY
  (
    SELECT TOP 1 SensorValue
      FROM SensorValues
      WHERE  SensorId = 53
        AND DeviceId = 3819
        AND "Date" < 1339225010
        AND $Partition.PF(Date) = b.boundary_id
        ORDER BY Date DESC
  ) d
  ORDER BY d.Date DESC
)
SELECT SensorValue
FROM Top1

TÙY CHỌN MAXDOP 1 không giúp được gì. Như được chỉ định bởi @Martin Smith bên dưới, có vẻ như phân vùng là nguyên nhân gây ra nó ...
m__

Câu trả lời:


13

Đối với một bảng không được phân vùng, tôi nhận được kế hoạch sau đây

Kế hoạch 1

Có một vị từ tìm kiếm trên Seek Keys[1]: Prefix: DeviceId, SensorId = (3819, 53), Start: Date < 1339225010 .

Có nghĩa là SQL Server có thể thực hiện tìm kiếm bình đẳng trên hai cột đầu tiên và sau đó bắt đầu một phạm vi tìm kiếm bắt đầu từ 1339225010và đặt hàngFORWARD (như chỉ mục được xác định với [Date] DESC)

Các TOP nhà điều hành sẽ dừng lại yêu cầu thêm hàng từ tìm kiếm sau khi hàng đầu tiên được phát ra.

Khi tôi tạo sơ đồ phân vùng và chức năng

CREATE PARTITION FUNCTION PF (int)
AS RANGE LEFT FOR VALUES (1000, 1339225009 ,1339225010 , 1339225011);
GO
CREATE PARTITION SCHEME [MyPartitioningScheme]
AS PARTITION PF
ALL TO ([PRIMARY] );

Và điền vào bảng với dữ liệu sau

INSERT INTO [dbo].[SensorValues]    
/*500 rows matching date and SensorId, DeviceId predicate*/
SELECT TOP (500) 3819,53,1, ROW_NUMBER() OVER (ORDER BY (SELECT 0))           
FROM master..spt_values
UNION ALL
/*700 rows matching date but not SensorId, DeviceId predicate*/
SELECT TOP (700) 3819,52,1, ROW_NUMBER() OVER (ORDER BY (SELECT 0))           
FROM master..spt_values
UNION ALL 
/*1100 rows matching SensorId, DeviceId predicate but not date */
SELECT TOP (1100) 3819,53,1, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) + 1339225011      
FROM master..spt_values

Kế hoạch trên SQL Server 2008 trông như sau.

Kế hoạch 2

Số lượng hàng thực tế phát ra từ tìm kiếm là 500. Kế hoạch cho thấy tìm kiếm vị ngữ

Seek Keys[1]: Start: PtnId1000 <= 2, End: PtnId1000 >= 1, 
Seek Keys[2]: Prefix: DeviceId, SensorId = (3819, 53), Start: Date < 1339225010

Cho biết nó đang sử dụng phương pháp quét bỏ qua được mô tả ở đây

trình tối ưu hóa truy vấn được mở rộng để có thể thực hiện thao tác tìm kiếm hoặc quét với một điều kiện trên PartitionID (dưới dạng cột dẫn logic) và có thể là các cột khóa chỉ mục khác, sau đó có thể thực hiện tìm kiếm cấp hai, với một điều kiện khác trên một hoặc nhiều cột bổ sung, cho mỗi giá trị riêng biệt đáp ứng đủ điều kiện cho hoạt động tìm kiếm cấp đầu tiên.

Kế hoạch này là một kế hoạch nối tiếp và vì vậy đối với truy vấn cụ thể, bạn có vẻ như nếu SQL Server đảm bảo rằng nó đã xử lý các phân vùng theo thứ tự giảm dần date kế hoạch ban đầu với kế hoạch ban đầu TOPvẫn sẽ hoạt động và nó có thể dừng xử lý sau khi hàng khớp đầu tiên tìm thấy thay vì tiếp tục và xuất ra 49 trận đấu còn lại.

Trên thực tế, kế hoạch năm 2005 có vẻ như thực hiện phương pháp đó

Kế hoạch năm 2005

Tôi không chắc chắn nếu nó là thẳng về phía trước để có được những kế hoạch tương tự vào năm 2008 hoặc có thể nó sẽ cần một OUTER APPLYtrên sys.partition_range_valuesđể mô phỏng nó.



9

Rất nhiều người tin rằng một chỉ mục được nhóm đảm bảo một thứ tự sắp xếp trên đầu ra. Nhưng đó không phải là những gì nó làm; nó đảm bảo lưu trữ thứ tự trên đĩa.

Xem, ví dụ, bài blog này , và cuộc thảo luận dài hơn này .


1
Chà, trước đó, OP cũng nói, "Tôi đã nghĩ rằng vì tôi lưu trữ các giá trị được sắp xếp theo cột Ngày, nên việc sắp xếp sẽ không xảy ra [sic]." Vì vậy, ít nhất một phần của vấn đề là quan niệm sai lầm về những gì một chỉ số cụm làm. Tôi nghĩ rằng thật tốt khi nói thẳng ra.
Mike Sherrill 'Nhớ lại mèo'

Có lẽ tôi chỉ bướng bỉnh (vì vậy xin vui lòng tha thứ cho tôi ;-)). Nhưng dù sao, tôi đã đọc bài viết trên blog của Hugo Kornelis và nó khá dễ dàng. Tuy nhiên, trong ví dụ của mình, anh ta đang sử dụng một chỉ mục cụm và một chỉ mục không phân cụm, chỉ mục không phân cụm có kích thước nhỏ hơn và do đó được sử dụng trong kế hoạch thực hiện. Trong trường hợp của tôi, tôi chỉ có một chỉ mục được nhóm, máy chủ sql vẫn có thể trả về các giá trị theo thứ tự sai (nó không có chỉ mục nhỏ hơn để sử dụng và quét toàn bộ bảng quá chậm)?
m__

Tôi đã chuyển câu hỏi này sang một câu hỏi mới (ngoài chủ đề)
m__

5

Tôi đang suy đoán rằng SORT là cần thiết vì kế hoạch song song. Tôi dựa trên một số bài viết blog mờ và xa: nhưng tôi đã tìm thấy nó trên MSDN , điều này có thể hoặc không thể chứng minh điều này

Vì vậy, hãy thử với MAXDOP 1 và xem điều gì xảy ra ...

Tôi cũng gợi ý về bài đăng trên blog của @sql kiwi trên Simple Talk trong "Nhà điều hành trao đổi". Và "sự phụ thuộc DOP" ở đây


Mặc dù trước đây tôi không bận tâm đến việc thiết lập chức năng phân vùng date. Bây giờ tôi có và dường như phân vùng là thủ phạm với năm 2005 có thể hành xử tốt hơn cho truy vấn cụ thể này.
Martin Smith

1

Về cơ bản, bạn đã đúng - vì khóa chính theo thứ tự "DeviceId, SensorId, Date", dữ liệu trong khóa không được sắp xếp theo ngày, do đó không thể được sử dụng. Nếu khóa của bạn theo thứ tự khác "Ngày, DeviceId, SensorId", thì dữ liệu trong khóa sẽ được sắp xếp theo ngày, do đó có thể được sử dụng ...


Tôi đã thử thay đổi chìa khóa theo cách bạn đề cập, vì vậy đừng cảm thấy tiếc. Dù sao, sẽ thử tạo chỉ mục không phân cụm trên cả 3 cột và xem những gì mang lại cho tôi. (nhiệm vụ tìm kiếm chỉ số mất tích vẫn tiếp tục ... ;-))
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.