2009-06-22 50 views
9

Tôi đã có một bảng 5,651,744 hàng, với khóa chính được tạo thành từ 6 cột (int x 3, smallint, varchar (39), varchar (2)). Tôi đang tìm cách cải thiện hiệu suất với bảng này và một bảng khác chia sẻ khóa chính này cộng với cột bổ sung được thêm nhưng có 37m hàng.CHECKSUM() va chạm trong SQL Server 2005

Với dự đoán thêm cột để tạo khóa băm, tôi đã thực hiện phân tích và tìm thấy 18.733 xung đột.

SELECT SUM(CT) 
FROM (
     SELECT HASH_KEY 
       ,COUNT(*) AS CT 
     FROM (
       SELECT CHECKSUM(DATA_DT_ID, BANK_NUM, COST_CTR_NUM, 
           GL_ACCT_NUM, ACCT_NUM, APPN_CD) AS HASH_KEY 
       FROM CUST_ACCT_PRFTBLT 
       ) AS X 
     GROUP BY HASH_KEY 
     HAVING COUNT(*) > 1 
     ) AS Y 

SELECT COUNT(*) 
FROM CUST_ACCT_PRFTBLT 

Đó là về gấp đôi xấu với BINARY_CHECKSUM()

Điều này dường như quá cao (0,33%) đưa ra số lượng tương đối nhỏ của không gian nơi tôi bao gồm? Và nếu các va chạm cao như thế này, có lợi ích khi tham gia khóa sản xuất này đầu tiên trong tham gia với chi phí thêm 4 byte cho mỗi hàng không, vì bạn vẫn phải tham gia vào các cột thông thường để xử lý sự va chạm không thường xuyên?

+0

Bạn đang tham gia bao nhiêu hồ sơ? Bảng chi tiết có chỉ mục nhóm không? Rộng bao nhiêu? Nếu chỉ mục nhóm được mở rộng (tức là, nó bao gồm tất cả các FK), bạn có thể thả nó hoặc thay thế nó bằng một cột nhận dạng không? –

+0

Tại sao nó là một vấn đề cho bạn? Bạn cần làm gì? –

+0

Vấn đề là tôi có 200m số liệu thống kê có nguồn gốc để sản xuất từ ​​37m hàng thống kê và PIVOT để thực hiện các phép tính có trục chính trên một khóa rất lớn dẫn đến một ống chỉ mong muốn của tất cả 37m hàng đến tempdb. –

Trả lời

7

Tôi không thấy nơi thêm một checksum sẽ giúp bạn có được bất cứ điều gì với mức độ đó của collisons. Thậm chí 1 xung đột cũng là quá nhiều vì nó sẽ khiến bạn tham gia vào dữ liệu sai. Nếu bạn không thể đảm bảo được tham gia vào hồ sơ chính xác, nó là vô nghĩa nếu nó cải thiện hiệu suất nhưng messes với tính toàn vẹn dữ liệu. Điều này dường như là dữ liệu tài chính, vì vậy bạn nên thực sự chắc chắn rằng các truy vấn của bạn sẽ không trả lại kết quả xấu. Bạn thực sự có thể kết thúc ghi nợ hoặc ghi có sai tài khoản nếu có bất kỳ xung đột nào.

Nếu bạn thực hiện lộ trình này, Marc nói đúng rằng bạn nên tính toán trước mỗi lần tính toán nhiều lần. Có thể nếu bạn có thể làm cột precomputed (và bạn sẽ cần kích hoạt để giữ cho nó cập nhật) sau đó bạn có thể không cần phải tham gia vào tất cả sáu cột khác để đảm bảo không có va chạm. Sau đó, có thể bạn có thể có hiệu suất imporved. Tất cả những gì bạn có thể làm là kiểm tra lý thuyết của bạn. Nhưng hãy chắc chắn rằng bạn không có bất kỳ va chạm nào.

Bạn đã cân nhắc sử dụng khóa thay thế và sau đó chỉ mục duy nhất trên sáu trường khóa tự nhiên thay thế? Sau đó, bạn có thể tham gia vào khóa thay thế và có khả năng sẽ cải thiện hiệu suất một chút. Nó không thể có hiệu quả để tham gia vào sáu cột (một varchar) thay vì một chìa khóa thay thế. Tôi nhận ra từ kích thước của dữ liệu, điều này có thể khó khăn hơn để tái cấu trúc hơn trong một hệ thống phi sản xuất, nhưng thực sự nó có giá trị thời gian xuống để vĩnh viễn sửa chữa các vấn đề hiệu suất dai dẳng. Chỉ có bạn mới có thể nói thay đổi phức tạp như thế nào và sẽ khó khăn như thế nào khi thay đổi tất cả các sp hoặc truy vấn để tham gia tốt hơn. Tuy nhiên, nó có thể là khả thi để thử.

+0

Tôi sẽ phải tham gia vào surrgate VÀ tất cả các cột PK quá. Người đại diện sẽ cần phải là cột đầu tiên trong chỉ mục (rằng trình tối ưu hóa hy vọng sẽ chọn), nhưng TẤT CẢ các cột sẽ phải được tham gia. Có một ví dụ (chỉ là một tìm kiếm, không phải là một tham gia) trong tài liệu MSDN này: http://msdn.microsoft.com/en-us/library/ms189788 (SQL.90).aspx –

+0

Tại sao cần phải tham gia vào khóa thay thế và các cột khóa chính tự nhiên? Chìa khóa thay thế sẽ cần phải được thêm vào cả hai bảng, nhưng bạn sẽ sử dụng nó thay vì 6 trường mà bạn hiện đang sử dụng trong phần nối. – LanceSc

+0

Tôi thấy, một đại diện duy nhất thực sự thay vì chỉ là một băm. Thật không may, hệ thống kế thừa mà tôi đang thiết kế lại không có RI, vì vậy thực sự có các mục trong bảng chỉ mục hàng 37m không có mục nhập trong bảng PK hàng 5m. Tôi sẽ phải suy nghĩ về điều này. –

2

Nếu tổng kiểm tra của bạn giảm xuống còn 0,33% dữ liệu, thì tôi cho rằng nó hoạt động tốt ... đặc biệt nếu bạn sử dụng cột này kết hợp với các cột khác (được lập chỉ mục).

Tất nhiên, để có hiệu quả như một chỉ mục bạn có thể muốn tính toán và lưu trữ giá trị này khi chèn/cập nhật dữ liệu, với chỉ mục không được nhóm.

Tất nhiên, một chỉ số kéo dài thường xuyên trên các cột trong câu hỏi có thể làm chỉ là tốt hoặc tốt hơn ...

+0

Có, tôi đã lên kế hoạch sử dụng cột được tính liên tục. –

1

Nếu truy vấn của bạn có chọn lọc và chỉ mục nhóm bảng đường hẹp hoặc không tồn tại, thì chỉ mục không nhóm trên tổng kiểm tra trong bảng dòng sẽ cung cấp hiệu suất tốt.

Sau khi áp dụng bất kỳ tiêu chí nào có trong bảng tiêu đề, nó sẽ sử dụng tổng kiểm tra để thực hiện chỉ mục tìm kiếm trên chỉ mục không được nhóm. Bạn vẫn cần phải bao gồm các FK trong tham gia, nhưng các tiêu chí tham gia không kiểm tra sẽ được áp dụng tìm kiếm chỉ mục sau, tra cứu sau dấu trang. Rất hiệu quả.

Bạn muốn tối ưu hóa để tìm kiếm chỉ mục. Việc kiểm tra đã được chọn lọc cao. Việc thêm các FK sẽ làm tăng kích thước chỉ mục và I/O tương ứng, và sẽ không giúp trừ khi nó bao gồm đủ các trường khác để tránh tra cứu toàn bộ dấu trang.

Vì chỉ mục không nhóm sẽ chứa các phím phân cụm hoặc con trỏ heap, bạn muốn hoặc a) một khóa phân cụm nhỏ (ví dụ: cột nhận dạng int - 4 byte con trỏ) hoặc b) không có chỉ mục nhóm nào cả (Con trỏ 8 byte).

Nếu truy vấn của bạn không chọn lọc, hoặc nếu chỉ số nhóm bảng đường là rất lớn (toàn bộ bảng trừ một vài cột) thì tôi không biết liệu tổng kiểm có giúp được (điều hướng chỉ mục nhanh hơn không?). Trong mọi trường hợp, bạn sẽ muốn làm cho nó trở thành một nhóm hoặc bao gồm chỉ mục, và nếu bảng tiêu đề không được nhóm trên checksum đầu tiên, sẽ có nhiều phân loại.

Nếu bạn có khả năng chi phí lưu trữ và lập chỉ mục, một vài chỉ mục bao gồm - tiêu đề và chi tiết - có thể là cách để đi.

1

NẾU PRIMARY KEY của bạn được nhóm lại, thì mỗi chỉ mục bạn tạo sẽ chứa số này PRIMARY KEY.

Tham gia vào một giá trị băm sẽ sử dụng các bước sau:

  1. Xác định vị trí giá trị băm trong chỉ số chủ chốt
    • Xác định vị trí giá trị PRIMARY KEY trong các dữ liệu chỉ số
    • Sử dụng Clustered Index Seek để xác định vị trí PRIMARY KEY hàng trong bảng

Tham gia trên PRIMARY KEY sẽ chỉ sử dụng bước 3.

SQL Server, tuy nhiên, là đủ thông minh để thực hiện việc này vào tài khoản, và nếu bạn sẽ tham gia như thế này:

SELECT * 
FROM main_table mt 
JOIN CUST_ACCT_PRFTBLT cap 
ON  cap.HASH_KEY = mt.HASH_KEY 
     AND cap.DATA_DT_ID = mt.DATA_DT_ID 
     AND … 
WHERE mt.some_col = @filter_value 

, nó chỉ sẽ không sử dụng chỉ mục trên HASH_KEY, thay vào đó, nó sẽ sử dụng một đơn Clustered Index SeekFilter để đảm bảo giá trị băm phù hợp (và chúng sẽ luôn luôn).

Tóm tắt: chỉ cần tham gia trên PRIMARY KEY.

Sử dụng chỉ mục phụ, trước tiên bạn cần thực hiện tìm kiếm HASH_KEY vô dụng và sau đó vẫn cần tham gia vào số PRIMARY KEY.

+0

Vâng, tôi đã tránh quá nhiều cơ cấu lại quá trình này trong quá trình tái kỹ thuật này, nhưng vì PK quá rộng (và nhóm lại), tôi nghĩ tôi có thể trích xuất nó và sử dụng người thay thế. Trong trường hợp đó, hàm băm không liên quan. Vấn đề chính của tôi là có kết thúc các hàng trong CUST_ACCT_STAT không có PK phù hợp trong CUST_ACCT_PRFTBLT do RI xấu trong hệ thống ban đầu, vì vậy tôi cũng sẽ cần phải suy ra các hàng cho những người đó. –

6

Những gì tôi đã thấy rất nhiều người tô bóng cho đến nay là CHECKSUM có rất nhiều va chạm, bởi Microsoft's own admission. Nó thậm chí còn tồi tệ hơn MD5, trong đó có chia sẻ công bằng của các va chạm có ý nghĩa.

Nếu bạn đang tìm kiếm cột băm, hãy xem xét sử dụng HASHBYTES với SHA1 được chỉ định. SHA1 có nhiều va chạm ít có ý nghĩa hơn MD5 hoặc CHECKSUM. Do đó, không nên sử dụng CHECKSUM để xác định xem một hàng là duy nhất hay không, nhưng đúng hơn, đó là kiểm tra nhanh về độ trung thực của hai giá trị.Do đó, tỷ lệ va chạm của bạn phải là 0% với HASHBYTES, trừ khi bạn có các hàng trùng lặp (trong đó, là một PK, sẽ không bao giờ xảy ra).

Hãy nhớ rằng HASHBYTES sẽ cắt bớt bất kỳ thứ gì lớn hơn 8000 byte, nhưng PK của bạn ít hơn rất nhiều so với (tất cả nối), vì vậy bạn không nên gặp bất kỳ sự cố nào.

+1

Tôi đã tái cấu trúc lược đồ để sử dụng thay thế duy nhất thực sự trong một bảng thứ nguyên và đã làm cho khóa chính này của ba bảng. Hiệu suất được cải thiện nhiều. –