Tăng tốc độ tạo chỉ mục cụm lớn?


8

Tôi có một bàn lớn, số hàng của bảng là hơn 3 tỷ, không gian dữ liệu cho bảng này khoảng 120 GB.

Và CPU Intel Xeon E5645 @ 2.4GHz (2 bộ xử lý), 24 CPU, bộ nhớ 64G, máy chủ windows 64 bit 2008 R2 doanh nghiệp.

tôi chạy

create unique clustered index MyTable_IXC on tblFactFoo(barKey) on [PRIMARY]

Nhưng phải mất hơn 6 giờ (thực tế, nó đã báo cáo lỗi của khóa trùng lặp sau 6 giờ).

Khi chạy nó, cpu nhỏ hơn 10% và IO đĩa dưới 20M / s, thông thường khoảng 15M / s, tôi tự hỏi làm thế nào để cải thiện hiệu suất tạo chỉ mục cụm với phần cứng mạnh mẽ như vậy.


Đây có phải là doanh nghiệp SQL Server không? Cơ sở dữ liệu lưu trữ trên là gì?
usr

có, máy chủ SQL 2008 r2 doanh nghiệp. Về lưu trữ, bạn có ý nghĩa gì? Chỉ cần đĩa cứng, đĩa SCSI LOGUM VOLUME.

Câu trả lời:


4

Bạn sẽ cần xem loại chờ khi truy vấn đang chạy. Vấn đề là bạn cần các đĩa nhanh hơn vì việc xây dựng một chỉ mục trên một bảng lớn sẽ gây ra số lượng đọc và ghi MASSIVE.

Tóm lại, bạn sẽ cần đọc bảng 120 Gig, sắp xếp nó dựa trên khóa phân cụm (điều này sẽ gây ra một tấn tràn sang tempdb có thể viết 100 Gigs sang tempdb), sau đó viết chỉ mục được phân cụm vào cơ sở dữ liệu gây ra 120 hợp đồng viết.

Trên hết, bất kỳ chỉ mục không phân cụm nào trên bảng sẽ cần phải được xây dựng lại cùng một lúc để tất cả các chỉ mục đó cũng cần được đọc và viết lại (cùng với tất cả các lỗi tràn bộ nhớ đi kèm với việc xây dựng lại các chỉ mục không được phân cụm).

Bạn có thể tăng tốc mọi thứ bằng cách vô hiệu hóa các chỉ mục không phải cụm, sau đó xây dựng chúng theo cách thủ công sau khi chỉ mục cụm được xây dựng lại. Bạn sẽ muốn đảm bảo rằng người dùng cuối không thể chạm vào hệ thống trong khi các chỉ mục không được phân cụm đang được xây dựng vì hiệu suất truy vấn của họ sẽ rất tệ cho đến khi các chỉ mục không được phân cụm được tạo.

Giả sử Enterprise Edition bạn có thể tạo các chỉ mục thường được sử dụng sau đó cho phép người dùng quay lại, sau đó tạo các chỉ mục khác trực tuyến để người dùng làm việc.

Không có vấn đề gì bạn sẽ nhìn vào một cửa sổ bảo trì dài THỰC SỰ, nơi bạn sẽ đập các đĩa mạnh nhất có thể.


3

Dưới đây là một vài điều để đánh giá:

  1. Bật nén dữ liệu: có vẻ như bạn bị ràng buộc IO và có CPU dự phòng. Nén dữ liệu có thể là một sự đánh đổi tốt ở đây.
  2. Bật SORT_IN_TEMPDBlên Điều này có thể cải thiện đáng kể các mẫu IO (IO tuần tự hơn và ít phân mảnh hơn trong chỉ mục cuối cùng).
  3. Xây dựng chỉ mục thành một nhóm mới (được quy định). Một nhóm mới không bị phân mảnh để ít nhất bạn có thể thoát khỏi vấn đề đó. Sử dụng khởi tạo tập tin ngay lập tức.

Hoặc, tải dữ liệu được sắp xếp chính xác ở vị trí đầu tiên. Sau đó, bạn không cần phải xây dựng một chỉ mục nào cả. Điều này có những nhược điểm nhất định nhưng đáng để xem xét. Giải pháp tốt nhất có thể là tải vào một chỉ mục được phân vùng bằng cách sử dụng ORDERgợi ý cho tải hàng loạt. Một luồng nhập hàng loạt trên mỗi phân vùng và một phân vùng trên CPU hoặc trên mỗi đĩa vật lý.


1

Làm thế nào cá nhân tôi sẽ làm điều này:

  • Đổi tên TableA thành TableA_Old và tạo chế độ xem có tên TableA. Bằng cách đó, người dùng của bạn có thể tiếp tục làm việc.
  • Tạo một TableB mới, tạo các chỉ mục của bạn trên nó và bắt đầu sao chép dữ liệu từ TableA_Old vào TableB (hoặc sao chép dữ liệu đầu tiên và sau đó tạo các chỉ mục; ít nhất tôi sẽ tạo chỉ mục được nhóm trước và tất cả các chỉ mục khác sau khi dữ liệu được sao chép).
  • Sau khi tất cả điều này, thả chế độ xem TableA, đổi tên TableB -> TableA và thả TableA_Old. Hãy chắc chắn rằng bạn đã có các bản ghi cuối cùng được thêm vào TableA_Old. Nhược điểm: bạn sẽ cần nhiều không gian đĩa hơn, nhưng thời gian chết sẽ ít hơn.

Bây giờ tôi thấy rằng DevArt về cơ bản có cùng câu trả lời với tôi :-)
Koen D

0

Mỗi khi bạn tạo / tạo lại chỉ mục cụm, máy chủ bắt đầu đặt hàng các trang và đây là thủ tục đòi hỏi khá nhiều tài nguyên. Bàn của bạn là một cái lớn Tôi khuyên bạn nên chia bảng của mình thành nhiều bảng nhỏ hơn (nghĩa là thực hiện chuẩn hóa dữ liệu), nếu có thể. Hoặc bạn có thể tạo một bản sao trống của bảng này, thêm chỉ mục cụm trên bảng trống, nhập tất cả dữ liệu từ bảng chính của bạn và sau đó xóa bảng chính.

Ý tôi là như thế này -

CREATE TABLE dbo.tblFactFoo_New
(
      barKey INT NOT NULL
    , ...
)

CREATE UNIQUE CLUSTERED INDEX tblFactFoo_IXC ON tblFactFoo_New(barKey) ON [PRIMARY]

INSERT INTO dbo.tblFactFoo_New(barKey, ...)
SELECT barKey, ... 
FROM dbo.tblFactFoo
GROUP BY barKey, ... -- without duplicates
ORDER BY barKey

DROP TABLE dbo.tblFactFoo

sp_rename 'dbo.tblFactFoo_New', 'dbo.tblFactFoo'

0

Để tăng tốc độ của bất kỳ lệnh SQL nào, bạn nên có một cơ sở dữ liệu được thiết lập đúng, do đó tôi hy vọng rằng cơ sở dữ liệu của bạn được lưu trữ trên một đĩa khác và chủ và tempdb nằm trên đĩa riêng của chúng.

Điều đó đang được nói có một số yếu tố ảnh hưởng đến việc tạo chỉ mục: nếu bảng đã được sắp xếp và vì có vẻ như bạn đang xây dựng bảng này trên bảng HEAP, tôi sẽ nói rằng nó không được sắp xếp và thành phần khác là loại cột mà bạn đang tạo chỉ mục trên. Thông tin chứa trong một chỉ mục được phân cụm bị giới hạn bởi số lượng cột hoặc kích thước byte của các cột (tùy theo điều kiện nào đến trước) và do đó một số cột không phải là ứng cử viên tốt cho việc lập chỉ mục cụm.

Vì bạn đang tạo một chỉ mục duy nhất trên bảng heap, bạn nên dọn sạch nó để không có các giá trị trùng lặp. Điều này sẽ tránh cho bạn phải xây dựng lại chỉ mục.

Vì vậy, trước khi bạn chạy truy vấn tạo chỉ mục, hãy chạy cái này trước

SELECT 
   barKey
FROM
(
    SELECT 
        barKey, 
        COUNT(barKey) AS NoOfDuplicates 
    FROM 
        dbo.tblFactFoo WITH(NOLOCK)
    GROUP BY 
        barKey
)
WHERE
NoOfDuplicates > 1;

Sau khi bạn chạy tệp này và xử lý các bản ghi trùng lặp, bạn có thể chạy các phần sau, xin lưu ý rằng phần này sẽ sử dụng thêm dung lượng đĩa, do đó bạn sẽ cần ít nhất dung lượng bằng kích thước của bảng đó.

CREATE UNIQUE CLUSTERED INDEX IXC_MyTable ON dbo.tblFactFoo(barKey) WITH(SORT_IN_TEMPDB)
GO

Điều này sẽ buộc việc sắp xếp (cần thiết khi tạo chỉ mục) xảy ra trong cơ sở dữ liệu tempdb và sau đó chuyển nó trở lại và thay thế dữ liệu của bạn.

Một cách khác là tạo một bảng trùng lặp có cùng tên, clumns, v.v., thêm khóa cụm trên đó, trước khi bạn thêm bất kỳ bản ghi nào và sau đó thực hiện lệnh này:

MERGE INTO dbo.tblFactFoo AS source
USING dbo.tblFactFooIndexed AS destination ON source.barKey = destination.barKey
WHEN NOT MATCHED BY source THEN
INSERT INTO destination(col1, col2, barKey etc) VALUES (source.col1, source.col2, source.barKey etc)
WHEN MATCHED BY source AND (add extra conditions here if needed) THEN
-- INSERT / UPDATE or DELETE depending on how you want to handle duplicate keys

Vì đây là một hoạt động được thiết lập nên về mặt lý thuyết, nó hoạt động nhanh hơn nhiều vì máy chủ SQL hoạt động trên các bộ nhanh hơn sau đó nó hoạt động trên các hàng. Khi bạn đã hoàn tất, bỏ bảng đầu tiên và đổi tên bảng thứ hai.

Nếu bạn cần thêm trợ giúp với lệnh MERGE ở đây là liên kết đến nó trên MSDN: http://msdn.microsoft.com/en-us/l Library / bb510625.aspx

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.