Lỗi trong Rebuild trên SQL Server 2016 trở lên?


7

Tóm tắt câu hỏi

REBUILDChỉ mục cụm bị phân mảnh không hoạt động tốt, ngay cả sau khi chỉ mục. Nếu chỉ mục là REORGANIZEDhiệu suất tăng cho bảng / chỉ mục đã cho.

Tôi chỉ thấy hành vi bất thường này trên SQL Server 2016 trở lên, tôi đã thử nghiệm kịch bản này trên các phần cứng và phiên bản khác nhau (tất cả các máy cá nhân và tất cả đều có đĩa cứng xoay thông thường). Hãy cho tôi biết nếu cần thêm thông tin.

Đây có phải là một lỗi trong SQL Server 2016 trở đi không?


Tôi có thể cung cấp các chi tiết và phân tích đầy đủ với tập lệnh nếu có ai muốn, nhưng không cung cấp ngay bây giờ vì tập lệnh khá lớn và sẽ chiếm nhiều khoảng trống trong câu hỏi.

Vui lòng kiểm tra phiên bản ngắn hơn của tập lệnh mẫu được lấy từ liên kết được cung cấp bên dưới trong môi trường DEV của bạn nếu bạn có SQL Server 2016 trở lên.

KỊCH BẢN

-- SECTION 1
/*
Create a Test Folder in the machine and spefiy the drive in which you created
*/
USE MASTER

CREATE DATABASE RebuildTest
ON 
( NAME = 'RebuildTest',
    FILENAME = 'F:\TEST\RebuildTest_db.mdf',
    SIZE = 200MB,
    MAXSIZE = UNLIMITED,
    FILEGROWTH = 50MB )
LOG ON
( NAME = 'RebuildTest_log',
    FILENAME = 'F:\TEST\RebuildTest_db.ldf',
    SIZE = 100MB,
      MAXSIZE = UNLIMITED,
    FILEGROWTH = 10MB ) ;
GO

BEGIN TRAN

USE RebuildTest

select  top 1000000
row_number () over ( order by (Select null)) n into Numbers from
sys.all_columns  a cross  join  sys.all_columns

CREATE TABLE [DBO].FRAG3 (
Primarykey int NOT NULL ,
SomeData3 char(1000) NOT NULL )

ALTER TABLE DBO.FRAG3
ADD CONSTRAINT PK_FRAG3 PRIMARY KEY (Primarykey)

INSERT INTO [DBO].FRAG3
SELECT n , 'Some text..'
FROM Numbers
Where N/2 = N/2.0

Update DBO.FRAG3 SET Primarykey =  Primarykey-500001
Where  Primarykey>500001

COMMIT

 -- SECTION 2

SELECT @@VERSION

/*                                                       BEGIN PART FRAG1.1     */

----- BEGIN CLEANBUFFER AND DATABASE AND MEASURE TIME
CHECKPOINT;
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;
SET STATISTICS TIME ON
Select Count_Big (*) From [DBO].[FRAG3] Where Primarykey >0 Option (MAxDop 1)
SET STATISTICS TIME OFF

----- END CLEANBUFFER AND DATABASE AND MEASURE TIME

-------------BEGIN PART FRAG1.2: REBUILD THE INDEX AND TEST AGAIN

--BEGIN Rebuild the Index
Alter Table [DBO].[FRAG3] REBUILD
--END  Rebuild the Index

----- BEGIN CLEANBUFFER FROM DATABASE AND MEASURE TIME
CHECKPOINT;
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;
SET STATISTICS TIME ON
Select Count_Big (*) From [DBO].[FRAG3] Where Primarykey >0 Option (MAxDop 1)
SET STATISTICS TIME OFF
----- END CLEANBUFFER  FROM DATABASE AND MEASURE TIME

--BEGIN REORGANIZE the Index
ALTER INDEX ALL ON [DBO].[FRAG3] REORGANIZE ;
--END REORGANIZE the Index

----- BEGIN CLEANBUFFER  FROM DATABASE AND MEASURE TIME
CHECKPOINT;
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;
SET STATISTICS TIME ON
Select Count_Big (*) From [DBO].[FRAG3] Where Primarykey >0 Option (MAxDop 1)
SET STATISTICS TIME OFF
----- END CLEANBUFFER  FROM DATABASE AND MEASURE TIME

-------------BEGIN PART FRAG1.4: REBUILD THE INDEX AND TEST AGAIN

--BEGIN Rebuild the Index
Alter Table [DBO].[FRAG3] REBUILD
--END  Rebuild the Index

----- BEGIN CLEANBUFFER FROM DATABASE AND MEASURE TIME
CHECKPOINT;
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;
SET STATISTICS TIME ON
Select Count_Big (*) From [DBO].[FRAG3] Where Primarykey >0 Option (MAxDop 1)
SET STATISTICS TIME OFF
----- END CLEANBUFFER  FROM DATABASE AND MEASURE TIME

-------------END PART FRAG1.4: REBUILD THE INDEX AND TEST AGAIN

Các kết quả

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

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

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

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

Kết quả kiểm tra đĩa Crystal

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

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

Chi tiết

Tôi đang thấy một hành vi bất thường của công cụ lưu trữ (có thể) trên SQL Server 2016 trở lên, tôi đã tạo một bảng phân mảnh cao cho mục đích demo (đọc phân mảnh) sau đó xây dựng lại nó.

Ngay cả sau khi xây dựng lại, hiệu suất chỉ mục không tăng như mong đợi. Để đảm bảo mẫu truy cập dữ liệu phải theo thứ tự chính không theo định hướng IAM (Quét phân bổ thứ tự), tôi đã sử dụng biến vị ngữ phạm vi.

Ban đầu, tôi nghĩ có lẽ SQL Server 2016 trở lên mạnh hơn đối với các bản quét lớn. Để kiểm tra điều đó, tôi đã điều chỉnh số trang và số hàng nhưng mẫu hiệu suất không thay đổi. Tôi đã thử nghiệm tất cả trên một hệ thống cá nhân để tôi có thể nói rằng không có hoạt động người dùng nào khác đang diễn ra.

Tôi cũng đã thử nghiệm hành vi này trên các phần cứng khác ( tất cả đều có đĩa cứng xoay truyền thống ). Các mẫu hiệu suất gần như giống nhau.

Tôi đã kiểm tra tất cả các số liệu thống kê chờ chỉ có vẻ bình thường PAGELATCH_IO(sử dụng tập lệnh Paul Randal) ở đó. Tôi đã kiểm tra các trang dữ liệu bằng DMV sys.dm_db_database_page_allocationsthì cũng có vẻ ổn.

Nếu tôi sắp xếp lại bảng hoặc di chuyển tất cả dữ liệu sang một bảng mới với cùng một đĩa định nghĩa chỉ số thì hiệu suất IO sẽ tăng. Tôi đã kiểm tra điều này với perfmon và có vẻ như việc sắp xếp lại chỉ mục / bảng mới có thể thúc đẩy IO tuần tự và chỉ mục xây dựng lại vẫn sử dụng các lần đọc ngẫu nhiên mặc dù thực tế là cả hai đều có sự phân mảnh bên trong và bên ngoài.

Tôi đang đính kèm truy vấn đầy đủ với kết quả trên hệ thống của tôi mà tôi đã chụp. nếu các bạn có SQL Server 2016 trở lên hộp DEV, vui lòng kiểm tra điều này và chia sẻ kết quả của bạn.

CẢNH BÁO : Thử nghiệm này bao gồm một số lệnh không có giấy tờ và DROPCLEANBUFFERSdo đó không chạy ở máy chủ sản xuất.

Nếu đây thực sự là một lỗi tôi nghĩ tôi nên nộp nó.

Vì vậy, câu hỏi là: Nó thực sự là một lỗi hay tôi đang thiếu một cái gì đó;)

Liên kết (pastebin)

Tạo bảng phân mảnh

2 SP hỗ trợ CHẠY SAU KHI TẠO BẢNG

3 bài kiểm tra

4 Bất kỳ vấn đề với Rebuild

5 Đặt dữ liệu vào bảng mới

Liên kết: (Google Drive)

6 Kết quả tải xuống TRÊN HỆ THỐNG CỦA TÔI


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện . Vui lòng sử dụng cơ sở đó để xử lý sự cố thêm.
Paul White 9

Câu trả lời:


13

Các truy vấn trong câu hỏi thực hiện tính năng đọc trước SQL Server . Với tối ưu hóa hiệu suất đọc trước, công cụ lưu trữ SQL Server sẽ tìm nạp dữ liệu trong quá trình quét để các trang đã có trong bộ đệm bộ đệm khi cần truy vấn để có ít thời gian chờ đợi dữ liệu trong khi thực hiện truy vấn.

Sự khác biệt về thời gian thực hiện với tính năng đọc phản ánh mức độ (hoặc không) của hệ thống lưu trữ và API Windows xử lý các kích thước IO lớn cùng với sự khác biệt trong SQL Server đọc hành vi trước thay đổi theo phiên bản. Các phiên bản SQL Server cũ hơn (SQL Server 2008 R2 trong bài viết đã nói ở trên) giới hạn tiền xử lý ở kích thước 512K IO trong khi SQL Server 2016 và sau đó phát hành trước IO ở kích thước lớn hơn để tận dụng khả năng của phần cứng hàng hóa cấp sản xuất hiện đại (RAID và SSD). Hãy nhớ rằng SQL Server thường được tối ưu hóa để chạy trên phần cứng thế hệ hiện tại tại thời điểm phát hành, khai thác bộ đệm của bộ xử lý lớn hơn, kiến ​​trúc NUMA và khả năng băng thông IOPS / hệ thống lưu trữ. Hơn nữa, các phiên bản Enterprise / Developer cũng thực hiện tìm nạp trước mạnh mẽ hơn các phiên bản nhỏ hơn để tối đa hóa thông lượng hơn nữa.

Để hiểu rõ hơn lý do về hiệu suất khác nhau của SQL 2008 R2 so với các phiên bản sau, tôi đã thực hiện một phiên bản sửa đổi của tập lệnh của bạn trên một máy vật lý cũ hơn với các phiên bản khác nhau của SQL Server Developer Edition. Hộp kiểm tra này có cả ổ cứng 7200 RPM và SSD SATA, cho phép chạy cùng một bài kiểm tra trên cùng một máy với các hệ thống lưu trữ và phiên bản SQL khác nhau. Tôi đã chụp các sự kiện file_read và file_read_completed trong mỗi thử nghiệm với dấu vết Sự kiện mở rộng để phân tích chi tiết hơn về IO và thời gian.

Kết quả cho thấy hiệu năng gần như tương đương với tất cả các phiên bản SQL Server và các loại hệ thống lưu trữ ngoại trừ SQL Server 2012 và các phiên bản mới hơn trên một trục chính của ổ đĩa cứng sau khi xây dựng lại chỉ mục cụm. Thật thú vị, dấu vết XE chỉ hiển thị chế độ "Tiếp giáp" trong quá trình quét trước đọc trong SQL Server 2008 R2; dấu vết cho thấy chế độ "Scatter / Gather" đã được sử dụng trong tất cả các phiên bản khác. Tôi không thể nói nếu sự khác biệt này góp phần vào hiệu suất nhanh hơn.

Ngoài ra, phân tích dữ liệu theo dõi cho thấy các vấn đề SQL 2016 lớn hơn nhiều trong quá trình đọc trước và kích thước IO trung bình thay đổi theo loại lưu trữ. Điều này không nhất thiết có nghĩa là SQL Server điều chỉnh kích thước IO đọc trước dựa trên phần cứng vật lý mà thay vào đó, nó có thể điều chỉnh kích thước dựa trên các phép đo không xác định. Các heuristic được sử dụng bởi công cụ lưu trữ không được ghi lại và có thể thay đổi theo phiên bản và cấp độ bản vá.

Dưới đây là một bản tóm tắt về thời gian thử nghiệm. Tôi sẽ thêm nhiều thông tin được thu thập từ các dấu vết khi tôi có thêm thời gian (tiếc là kích thước IO không có sẵn trong SQL Server 2008 R2 XE). Tóm lại, cấu hình IO khác nhau theo phiên bản và loại lưu trữ. Kích thước IO trung bình cho các phiên bản thông qua SQL Server 2014 không bao giờ vượt quá 512K trong khi SQL Server 2016 đọc hơn 4 MB trong một IO trong các thử nghiệm này. Số lần đọc xuất sắc cũng ít hơn nhiều trong bài kiểm tra SQL 2016 vì SQL Server ít yêu cầu IO hơn để thực hiện cùng một công việc.

SQL_Version Storage Device         Test                   Duration
SQL 2008 R2    HDD             initial table            00:00:03.686
SQL 2012       HDD             initial table            00:00:03.725
SQL 2014       HDD             initial table            00:00:03.706
SQL 2016       HDD             initial table            00:00:03.654
SQL 2008 R2    HDD             fragmented table         00:00:07.796
SQL 2012       HDD             fragmented table         00:00:08.026
SQL 2014       HDD             fragmented table         00:00:07.837
SQL 2016       HDD             fragmented table         00:00:06.097
SQL 2008 R2    HDD             after rebuild            00:00:06.962
SQL 2012       HDD             after rebuild            00:00:21.129
SQL 2014       HDD             after rebuild            00:00:19.501
SQL 2016       HDD             after rebuild            00:00:21.377
SQL 2008 R2    HDD             after reorg              00:00:04.103
SQL 2012       HDD             after reorg              00:00:03.974
SQL 2014       HDD             after reorg              00:00:04.076
SQL 2016       HDD             after reorg              00:00:03.610
SQL 2008 R2    HDD             after reorg and rebuild  00:00:07.201
SQL 2012       HDD             after reorg and rebuild  00:00:21.839
SQL 2014       HDD             after reorg and rebuild  00:00:20.199
SQL 2016       HDD             after reorg and rebuild  00:00:21.782
SQL 2008 R2    SATA SSD        initial table            00:00:02.083
SQL 2012       SATA SSD        initial table            00:00:02.071
SQL 2014       SATA SSD        initial table            00:00:02.074
SQL 2016       SATA SSD        initial table            00:00:02.066
SQL 2008 R2    SATA SSD        fragmented table         00:00:03.134
SQL 2012       SATA SSD        fragmented table         00:00:03.129
SQL 2014       SATA SSD        fragmented table         00:00:03.129
SQL 2016       SATA SSD        fragmented table         00:00:03.113
SQL 2008 R2    SATA SSD        after rebuild            00:00:02.065
SQL 2012       SATA SSD        after rebuild            00:00:02.097
SQL 2014       SATA SSD        after rebuild            00:00:02.071
SQL 2016       SATA SSD        after rebuild            00:00:02.078
SQL 2008 R2    SATA SSD        after reorg              00:00:02.064
SQL 2012       SATA SSD        after reorg              00:00:02.082
SQL 2014       SATA SSD        after reorg              00:00:02.067
SQL 2016       SATA SSD        after reorg              00:00:02.072
SQL 2008 R2    SATA SSD        after reorg and rebuild  00:00:02.078
SQL 2012       SATA SSD        after reorg and rebuild  00:00:02.087
SQL 2014       SATA SSD        after reorg and rebuild  00:00:02.087
SQL 2016       SATA SSD        after reorg and rebuild  00:00:02.079

Tôi cũng đã chạy các thử nghiệm này trên máy ảo có SAN được hỗ trợ bởi ổ cứng và quan sát hiệu năng tương tự như SSD SSD. Vì vậy, điểm mấu chốt là vấn đề hiệu năng này chỉ xảy ra với một tệp dữ liệu ổ cứng một trục, một điều chỉ phổ biến trên PC, không phải hệ thống sản xuất hiện đại. Có nên xem đây có phải là lỗi hồi quy hiệu suất hay không nhưng tôi sẽ liên hệ để xem liệu tôi có thể nhận thêm thông tin hay không.

BIÊN TẬP

Tôi đã liên hệ với các liên hệ của mình và Erland Sommarskog đã chỉ ra số lượng phân đoạn cao hơn được báo cáo bởi sys.dm_db_index_physical_stats trong các phiên bản sau. Tìm hiểu sâu hơn, tôi nhận thấy câu lệnh REBUILD là một truy vấn song song. Hàm ý là việc xây dựng lại song song thực sự có thể làm tăng số lượng phân đoạn (và thậm chí giới thiệu phân mảnh trên bảng không có phân mảnh) vì phân bổ không gian được thực hiện song song. Điều này thường sẽ không ảnh hưởng đến hiệu suất ngoại trừ quét trước và đặc biệt là vấn đề với phương tiện kéo sợi trục đơn như các thử nghiệm cho thấy. Đây là một sự cân nhắc trong tất cả các phiên bản SQL.

Paul Randal đã chỉ ra điều này theo thiết kế và tham khảo tài liệu này để biết thêm thông tin. Một cách thực hành tốt nhất để xây dựng lại chỉ mục cho một khối lượng công việc sẽ thúc đẩy các lần quét trước đọc (ví dụ: kho dữ liệu) là xây dựng lại WITH (MAXDOP = 1);

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.