Tại sao phải mất nhiều thời gian hơn để tạo một chỉ mục sau khi tăng kích thước cột?


18

Nhà cung cấp của chúng tôi đã thay đổi độ rộng cột trên hầu hết các cột trong toàn bộ cơ sở dữ liệu. Cơ sở dữ liệu khoảng 7TB, hơn 9000 bảng. Chúng tôi đang cố gắng tạo một chỉ mục trên một bảng có 5,5 tỷ hàng. Trước khi nâng cấp của nhà cung cấp, chúng tôi có thể tạo chỉ mục trong 2 giờ. Bây giờ phải mất nhiều ngày. Những gì họ đã làm là tăng bất kỳ kích thước varchar (xx) nào lên varchar (256). Vì vậy, hầu hết các cột được sử dụng là varchar (18) hoặc varchar (75), v.v.

Dù sao, khóa chính bao gồm 6 cột có chiều rộng kết hợp là 126 ký tự. Bây giờ sau khi nâng cấp, khóa chính là 1283 ký tự vi phạm giới hạn Máy chủ SQL là 900 ký tự. Toàn bộ chiều rộng cột của bảng đã đi từ tổng số varchar kết hợp là 1049 đến tổng số varchar kết hợp là 4009.

Không có sự gia tăng dữ liệu, bảng không chiếm nhiều "không gian" hơn trước khi tăng chiều rộng cột, nhưng hiệu suất để tạo ra thứ gì đó đơn giản như một chỉ mục hiện đang chiếm một lượng thời gian không hợp lý.

Bất cứ ai cũng có thể giải thích tại sao phải mất quá nhiều thời gian để tạo và lập chỉ mục khi điều duy nhất được thực hiện là tăng kích thước của các cột?

Chỉ mục chúng tôi đang cố gắng tạo không độc quyền vì pk là chỉ mục được nhóm. Sau nhiều lần thử tạo chỉ mục, chúng tôi đã từ bỏ. Tôi nghĩ rằng nó đã chạy 4 hoặc 5 ngày mà không hoàn thành.

Tôi đã thử điều này trong một môi trường phi sản xuất bằng cách chụp ảnh hệ thống tệp và đưa cơ sở dữ liệu lên một máy chủ yên tĩnh hơn.

Câu trả lời:


12

Remus đã chỉ ra một cách hữu ích rằng độ dài tối đa của VARCHARcột ảnh hưởng đến kích thước hàng ước tính và do đó bộ nhớ cấp cho SQL Server.

Tôi đã cố gắng nghiên cứu thêm một chút để mở rộng phần "từ điều này trên tầng thác" trong câu trả lời của anh ấy. Tôi không có một lời giải thích đầy đủ hoặc súc tích, nhưng đây là những gì tôi tìm thấy.

Kịch bản repro

Tôi đã tạo một tập lệnh đầy đủ để tạo một tập dữ liệu giả mà việc tạo chỉ mục mất khoảng 10 lần trên máy của tôi cho VARCHAR(256)phiên bản. Dữ liệu sử dụng là giống hệt nhau, nhưng bảng đầu tiên sử dụng độ dài tối đa thực tế của 18, 75, 9, 15, 123, và 5, trong khi tất cả các cột sử dụng một chiều dài tối đa của 256trong bảng thứ hai.


Khóa bảng gốc

Ở đây chúng ta thấy rằng truy vấn ban đầu hoàn thành trong khoảng 20 giây và số lần đọc logic bằng với kích thước bảng của ~1.5GB(195K trang, 8K mỗi trang).

-- CPU time = 37674 ms,  elapsed time = 19206 ms.
-- Table 'testVarchar'. Scan count 9, logical reads 194490, physical reads 0
CREATE CLUSTERED INDEX IX_testVarchar
ON dbo.testVarchar (s1, s2, s3, s4)
WITH (MAXDOP = 8) -- Same as my global MAXDOP, but just being explicit
GO


Khóa bảng VARCHAR (256)

Đối với VARCHAR(256)bảng, chúng tôi thấy rằng thời gian trôi qua đã tăng lên đáng kể.

Thật thú vị, cả thời gian CPU và số lần đọc logic đều không tăng. Điều này có ý nghĩa khi bảng có cùng dữ liệu, nhưng nó không giải thích được tại sao thời gian trôi qua chậm hơn nhiều.

-- CPU time = 33212 ms,  elapsed time = 263134 ms.
-- Table 'testVarchar256'. Scan count 9, logical reads 194491
CREATE CLUSTERED INDEX IX_testVarchar256
ON dbo.testVarchar256 (s1, s2, s3, s4)
WITH (MAXDOP = 8) -- Same as my global MAXDOP, but just being explicit
GO


Số liệu thống kê I / O và chờ đợi: bản gốc

Nếu chúng ta nắm bắt chi tiết hơn một chút (sử dụng p_perfMon, một thủ tục mà tôi đã viết ), chúng ta có thể thấy rằng phần lớn I / O được thực hiện trên LOGtệp. Chúng tôi thấy số lượng I / O tương đối khiêm tốn trên thực tế ROWS(tệp dữ liệu chính) và loại chờ chính là LATCH_EX, biểu thị sự tranh chấp trong bộ nhớ.

Chúng ta cũng có thể thấy rằng đĩa quay của tôi nằm ở đâu đó giữa "xấu" và "cực kỳ tệ", theo Paul Randal :)

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


Số liệu thống kê I / O và chờ: VARCHAR (256)

Đối với VARCHAR(256)phiên bản, số liệu thống kê I / O và chờ hoàn toàn khác nhau! Ở đây, chúng ta thấy sự gia tăng rất lớn của I / O trên tệp dữ liệu ( ROWS) và thời gian ngừng hoạt động khiến Paul Randal chỉ đơn giản nói "WOW!".

Không có gì đáng ngạc nhiên khi loại chờ đợi số 1 bây giờ IO_COMPLETION. Nhưng tại sao I / O được tạo ra nhiều như vậy?

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


Gói truy vấn thực tế: VARCHAR (256)

Từ kế hoạch truy vấn, chúng ta có thể thấy rằng Sorttoán tử có một sự cố tràn đệ quy (sâu 5 cấp!) Trong VARCHAR(256)phiên bản của truy vấn. (Không có sự cố tràn nào trong phiên bản gốc.)

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


Tiến trình truy vấn trực tiếp: VARCHAR (256)

Chúng tôi có thể sử dụng sys.dm_exec_query_profiles để xem tiến trình truy vấn trực tiếp trong SQL 2014+ . Trong phiên bản gốc, toàn bộ Table ScanSortđược xử lý mà không có sự cố tràn ( spill_page_countvẫn còn 0trong suốt).

VARCHAR(256)Tuy nhiên, trong phiên bản, chúng ta có thể thấy rằng sự cố tràn trang nhanh chóng tích lũy cho người Sortvận hành. Dưới đây là ảnh chụp tiến trình truy vấn ngay trước khi truy vấn hoàn tất. Dữ liệu ở đây được tổng hợp trên tất cả các chủ đề.

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

Nếu tôi đào sâu vào từng luồng riêng lẻ, tôi thấy rằng 2 luồng hoàn thành sắp xếp trong vòng khoảng 5 giây (tổng thể @ 20 giây, sau 15 giây dành cho việc quét bảng). Nếu tất cả các luồng tiến triển với tốc độ này, việc VARCHAR(256)tạo chỉ mục sẽ hoàn thành gần như cùng lúc với bảng gốc.

Tuy nhiên, 6 luồng còn lại tiến triển với tốc độ chậm hơn nhiều. Điều này có thể là do cách phân bổ bộ nhớ và cách các luồng được giữ bởi I / O khi chúng tràn dữ liệu. Tôi không biết chắc chắn mặc dù.

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


Bạn có thể làm gì?

Có một số điều bạn có thể cân nhắc thử:

  • Làm việc với nhà cung cấp để quay lại phiên bản trước. Nếu điều đó là không thể, hãy để nhà cung cấp mà bạn không hài lòng với thay đổi này để họ có thể xem xét hoàn nguyên nó trong phiên bản tương lai.
  • Khi thêm chỉ số của bạn, hãy xem xét sử dụng OPTION (MAXDOP X)ở đâu Xlà một con số thấp hơn so với thiết lập máy chủ cấp hiện tại của bạn. Khi tôi sử dụng OPTION (MAXDOP 2)trên tập dữ liệu cụ thể này trên máy của mình, VARCHAR(256)phiên bản đã hoàn thành 25 seconds(so với 3-4 phút với 8 luồng!). Có thể hành vi đổ tràn bị làm trầm trọng thêm bởi tính song song cao hơn.
  • Nếu đầu tư phần cứng bổ sung là một khả năng, hãy lập hồ sơ I / O (nút cổ chai có khả năng) trên hệ thống của bạn và xem xét sử dụng ổ SSD để giảm độ trễ của I / O do sự cố tràn.


đọc thêm

Paul White có một bài đăng blog tốt đẹp về các loại nội bộ của SQL Server có thể được quan tâm. Nó nói một chút về việc đổ, xiên chuỗi và cấp phát bộ nhớ cho các loại song song.


11

Bảng sắp xếp trung gian sẽ được ước tính khác nhau giữa hai trường hợp. Điều này sẽ dẫn đến các yêu cầu cấp bộ nhớ khác nhau ( VARCHAR(256)sẽ lớn hơn) và có thể là một khoản trợ cấp thực tế nhỏ hơn nhiều, phần trăm khôn ngoan, so với yêu cầu 'lý tưởng'. Tôi đoán điều này dẫn đến sự cố tràn trong quá trình sắp xếp.

Kiểm tra tập lệnh từ Geoff (chỉ trên 100 nghìn hàng) Tôi có thể thấy rõ sự khác biệt về kích thước hàng ước tính sắp xếp (141B so với 789B). Từ đây về những thứ thác.


8
Tôi chắc chắn Paul sẽ chứng minh một câu trả lời thấu đáo và đầy đủ hơn, bao gồm cả các cuộc gọi có lẽ, sẽ được sử dụng làm tài liệu học tập của nhóm nhà phát triển. Một lần nữa ...
Remus Rusanu
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.