Cờ và bảng chia


9

Tôi đang thiết kế một bảng các mặt hàng sẽ (có khả năng) chứa hàng chục triệu hồ sơ. Một số mặt hàng sẽ không có sẵn để sử dụng cho đến khi chúng được "phê duyệt" bởi quản trị viên. Bằng cách "sử dụng" Tôi có nghĩa là các mục đó sẽ không được tham chiếu trong bất kỳ bảng nào khác cho đến khi chúng được "phê duyệt". Lên đến 50% các mặt hàng có thể "không được chấp thuận" tại bất kỳ thời điểm nào. Hồ sơ có thể trở thành "được phê duyệt", nhưng không phải ngược lại.

Tôi xem xét hai lựa chọn thiết kế:

  • một chút cờ
  • một bảng riêng biệt của các mục "không được chấp thuận" - khi mục được phê duyệt, nó được chuyển sang bảng "thông thường" (việc gia hạn ID của mục không phải là vấn đề)

Tôi nghĩ rằng lựa chọn thứ hai là tốt hơn nhiều. Cờ bit chỉ mất một byte trên mỗi hàng, vì vậy nó không phải là vấn đề. Nhưng nếu chúng ta có một triệu hồ sơ được phê duyệt và một triệu hồ sơ chưa được phê duyệt trong cùng một bảng - thì thời gian quét sẽ tăng lên đối với các hoạt động có hồ sơ được phê duyệt.

Câu hỏi là: tôi nên xem xét tùy chọn đầu tiên (cờ bit)? Liệu nó có bất kỳ lợi ích trong tình huống được mô tả?


1
Nó có thể giúp nhớ rằng bạn có thể sử dụng các chỉ mục được lọc để giúp tăng tốc truy cập vào các hồ sơ được phê duyệt. brentozar.com/archive/2013/11/ từ
mendosi

Thật không may, các chỉ mục được lọc không được sử dụng trong các truy vấn tham số.
Dima

@Dima điều đó không hoàn toàn đúng. Nếu một chỉ mục được lọc có nói WHERE status='A'và một truy vấn có WHERE status = 'A' AND (... other columns and parameters here...), thì chỉ mục đó vẫn có thể được sử dụng.
ypercubeᵀᴹ

Câu trả lời:


6

Bạn có thể có cả hai cách với các khung nhìn được phân vùng .

Bạn tạo một bảng cơ bản cho từng trạng thái, được thi hành bởi các ràng buộc, với các giá trị loại trừ lẫn nhau. Sau đó, một khung nhìn mà UNION kết hợp các bảng bên dưới. Khung nhìn hoặc mỗi bảng cơ sở có thể được tham chiếu rõ ràng. Nếu trạng thái của một hàng là UPDATEd thông qua chế độ xem, DBMS sẽ XÓA nó từ một bảng cơ sở và chèn nó vào một bảng tương ứng với trạng thái mới. Mỗi bảng cơ sở có thể được lập chỉ mục độc lập theo mô hình sử dụng của nó. Trình tối ưu hóa sẽ giải quyết các tham chiếu chỉ mục đến một bảng cơ sở tương ứng nếu có thể.

Những lợi ích là
một) chỉ số nông hơn. Tuy nhiên, làm toán trên chỉ số fan-out. Ở tỷ lệ đó và phân chia giữa các giá trị trạng thái của bạn, có thể các chỉ mục sẽ có cùng độ sâu trên các bảng phân chia như chúng sẽ nằm trên bảng kết hợp.
b) không có mã ứng dụng phải thay đổi. Dữ liệu tiếp tục xuất hiện dưới dạng tổng thể liên tục.
c) các giá trị trạng thái mới trong tương lai có thể được bao gồm bằng cách thêm bảng cơ sở mới, với ràng buộc và tạo lại chế độ xem.

Chi phí là tất cả sự di chuyển dữ liệu đó; hai trang và các chỉ mục liên quan được viết cho mỗi cập nhật trạng thái. Rất nhiều IO để giải quyết. Chuyển động nhiều cũng sẽ gây ra sự phân mảnh.


5

một bảng các mục sẽ (có khả năng) chứa hàng chục triệu bản ghi.

Điều đó thực sự không nhiều, dựa trên những gì SQL Server có thể xử lý một cách hiệu quả. Tất nhiên, tôi nhớ một trong những công việc trước đây của tôi khi một trong những bảng lớn nhất (một hệ thống đơn lẻ) có 2 triệu hàng và đó là công việc nhiều nhất tôi từng xử lý. Sau đó, công việc tiếp theo có 17 trường hợp sản xuất với một số bảng có hàng trăm triệu hàng và tất cả được tổng hợp thành Kho dữ liệu với nhiều bảng thực tế có hơn 1 tỷ hàng. Đừng hiểu sai ý tôi, tôi không chế giễu hàng chục triệu hàng, tôi chỉ nhấn mạnh rằng với một mô hình dữ liệu tốt và lập chỉ mục đúng (và bảo trì chỉ mục), SQL Server có thể xử lý rất nhiều .

Lên đến 50% các mặt hàng có thể "không được chấp thuận" tại bất kỳ thời điểm nào.

Hừm. Điều đó không đúng. Tỷ lệ mục "phê duyệt" sẽ bằng một nửa tỷ lệ nhận mục mới? Cứ 2 mục mới, chỉ có 1 mục sẽ được "phê duyệt"? Trong ví dụ của bạn về 2 triệu hàng và 1 triệu mỗi hàng cho "được phê duyệt" và "không được chấp thuận", một vài năm sau với 10 triệu mục khác, bạn có mong đợi 6 triệu cho mỗi mục "được phê duyệt" và "không được chấp thuận" không? Hay là 1 triệu "không được chấp thuận" sẽ vẫn không thay đổi, như vậy với 10 triệu mục mới, sẽ có 11 triệu "được phê duyệt" và vẫn còn 1 triệu "không được chấp thuận"?

Hồ sơ có thể trở thành "được phê duyệt", nhưng không phải ngược lại.

Điều đó là đúng ngày hôm nay , nhưng mọi thứ thay đổi theo thời gian và do đó, luôn có khả năng doanh nghiệp có thể quyết định cho phép "không chấp thuận", hoặc có thể một số trạng thái khác, chẳng hạn như "được lưu trữ", v.v.

Vì vậy, hãy nhìn vào các lựa chọn:

Cờ (hoặc thậm chí có thể là TINYINT"trạng thái")

  • Hơi chậm cho các truy vấn của từng trạng thái
  • Linh hoạt hơn theo thời gian / dễ dàng kết hợp một thay đổi, chẳng hạn như trạng thái thứ ba (ví dụ: "Đã lưu trữ") chỉ với một giá trị trạng thái Tra cứu mới. Không có bảng mới (nhất thiết), một số mã mới, chỉ một số mã được cập nhật.
  • Ít công việc hơn (ví dụ mã, kiểm tra, v.v.) và ít lỗi hơn khi cập nhật một TINYINTcột
  • Ít phức tạp hơn = chi phí bảo trì thấp hơn theo thời gian, thời gian đào tạo ngắn hơn cho nhân viên mới để tìm ra
  • (có thể) Tác động nhỏ hơn đến Nhật ký giao dịch khi một bảng được cập nhật
  • Chỉ cần một bảng Tra cứu cho "RecordStatus" và FK giữa hai bảng.

Hai bảng riêng biệt (một cho "đã được phê duyệt", một cho "không được chấp thuận")

  • Nhanh hơn một chút cho các truy vấn của từng trạng thái
  • Ít linh hoạt hơn theo thời gian / khó hơn để kết hợp một thay đổi, chẳng hạn như trạng thái thứ ba (ví dụ: "Đã lưu trữ"); trạng thái mới sẽ yêu cầu nhiều khả năng là một bảng khác, và chắc chắn là mã mới và được cập nhật.
  • Nhiều công việc hơn (ví dụ mã, kiểm tra, v.v.) và nhiều chỗ hơn cho việc di chuyển các bản ghi lỗi từ bảng "Chưa được phê duyệt" sang bảng "Đã phê duyệt"
  • Phức tạp hơn = chi phí bảo trì cao hơn theo thời gian, thời gian đào tạo dài hơn cho nhân viên mới để tìm ra
  • (có thể) Tác động lớn hơn đến Nhật ký giao dịch khi một bảng bị xóa và một bảng được chèn
  • Không cần phải lo lắng về việc " gia hạn ID của mặt hàng ": Bảng chưa IDENTITYđược phê duyệt có cột ID là một cột và bảng được phê duyệt có cột ID không phải là một IDENTITY(vì không cần thiết ở đó). Do đó, giá trị ID vẫn nhất quán khi di chuyển bản ghi giữa các bảng.

Cá nhân, tôi sẽ nghiêng về bảng duy nhất với StatusIDcột để bắt đầu. Sử dụng hai bảng có vẻ như là một tối ưu hóa quá phức tạp, quá sớm. Loại tối ưu hóa đó có thể được thảo luận nếu / khi số lượng bản ghi trong vài trăm triệu lập chỉ mục không cung cấp bất kỳ mức tăng hiệu suất nào.


Đó là một bảng có dữ liệu chuyển động nhanh: khá thường xuyên có nhiều hàng mới, khá thường xuyên bị xóa hàng. Tôi đã cố gắng loại bỏ tất cả các chi tiết (như quyết định kinh doanh, mã hóa khách hàng, v.v.) để chỉ tập trung vào một chủ đề duy nhất. Về cơ bản chúng ta có bảng thiết kế cũ với một chút cờ. Và tôi biết 100% rằng các hàng trong đó cờ được đặt thành 1 không bao giờ được sử dụng trong bất kỳ bảng nào khác. Vì vậy, tôi cảm thấy rằng chúng chỉ diễn ra ở đó và có thể được chuyển đến một bảng riêng biệt. Bảng được quét gần như trên mọi truy vấn tới DB. Vì vậy, giảm "trọng lượng" của nó có khả năng có thể giảm ops CPU / IO.
Dima

3
Một ưu điểm khác của các bảng phân chia: Bạn có thể có các FK chỉ tham chiếu bảng "Đã phê duyệt".
ypercubeᵀᴹ

Vấn đề khác với các bảng phân chia cho một thực thể là ràng buộc ràng buộc. Tài liệu tham khảo từ các bảng khác sẽ không chơi tốt với bản ghi di chuyển. Điều này sẽ yêu cầu viết mã để khắc phục các vấn đề này, chẳng hạn như các bảng tham chiếu nhân bản cho bảng phân chia -> Rất rắc rối
user1567453
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.