GUID tuần tự hoặc bigint cho PK cơ sở dữ liệu 'khổng lồ'


14

Tôi biết loại câu hỏi này xuất hiện rất nhiều, nhưng tôi chưa đọc bất kỳ lý lẽ thuyết phục nào để giúp tôi đưa ra quyết định này. Xin vui lòng chịu với tôi!

Tôi có một cơ sở dữ liệu khổng lồ - nó tăng khoảng 10.000.000 hồ sơ mỗi ngày. Dữ liệu là quan hệ và vì lý do hiệu suất, tôi tải bảng bằng BULK COPY. Vì lý do này, tôi cần tạo khóa cho các hàng và không thể dựa vào cột IDENTITY.

Một số nguyên 64 bit - một bigint - đủ rộng để tôi sử dụng, nhưng để đảm bảo tính duy nhất, tôi cần một trình tạo tập trung để tạo ID cho tôi. Tôi hiện có một dịch vụ tạo như vậy cho phép một dịch vụ dự trữ số thứ tự X và đảm bảo không có va chạm. Tuy nhiên, hậu quả của việc này là tất cả các dịch vụ tôi có đều phụ thuộc vào một máy phát tập trung này, và vì vậy tôi bị hạn chế trong cách tôi có thể phân phối hệ thống của mình và không hài lòng về các phụ thuộc khác (như yêu cầu truy cập mạng) bởi thiết kế này. Điều này đã được một vấn đề trong dịp.

Bây giờ tôi đang xem xét sử dụng GUID tuần tự làm khóa chính của mình (được tạo bên ngoài thành SQL). Theo như tôi đã có thể xác định từ thử nghiệm của riêng mình, thì nhược điểm duy nhất của nó là chi phí không gian đĩa của loại dữ liệu rộng hơn (bị làm trầm trọng hơn khi sử dụng chúng trong các chỉ mục). Tôi đã không chứng kiến ​​bất kỳ sự chậm lại rõ rệt nào trong hiệu suất truy vấn, so với thay thế bigint. Tải bảng bằng BULK COPY chậm hơn một chút, nhưng không nhiều. Các chỉ mục dựa trên GUID của tôi không bị phân mảnh nhờ triển khai GUID tuần tự của tôi.

Về cơ bản, những gì tôi muốn biết là nếu có bất kỳ cân nhắc nào khác mà tôi có thể đã bỏ qua. Hiện tại, tôi có xu hướng thực hiện bước nhảy vọt và bắt đầu sử dụng GUID. Tôi không có nghĩa là một chuyên gia cơ sở dữ liệu, vì vậy tôi thực sự đánh giá cao bất kỳ hướng dẫn.


2
Làm thế nào bạn sẽ tạo ra một "GUID tuần tự"?

Đó là một thực hiện tùy chỉnh. Về cơ bản, nó là định dạng kiểu GUID có 6 byte được thay thế bằng byte dấu thời gian và 2 byte đại diện cho số thứ tự trong đó dấu thời gian giống nhau. Nó không được đảm bảo để tạo ra các giá trị tuần tự hoàn hảo, nhưng nó đủ tốt để biến phân mảnh chỉ mục thành vấn đề đối với tôi.

Do đó, bạn đang tải dữ liệu này từ nhiều nguồn khác nhau? Tôi cũng cho rằng chỉ số bạn lo lắng về phân mảnh là chỉ mục được nhóm?

2
Nếu bạn đang sử dụng GUID tuần tự, bạn nên xem NEWSEQUENTIALID (). Nó nên làm những gì bạn muốn (tăng đơn điệu) và không dựa vào mã tùy chỉnh.

2
Hãy xem bài đăng của Jeremiah Peschka về Sự cố với chìa khóa Đọc tốt và anh ấy đã xử lý việc thực hiện này nhiều lần.
billinkc

Câu trả lời:


4

Tôi cũng ở trong hoàn cảnh tương tự. Hiện tại, tôi đang sử dụng phương pháp GUID tuần tự và không có phân mảnh và tạo khóa dễ dàng.

Tôi đã nhận thấy hai sự biến dạng khiến tôi bắt đầu chuyển sang bigint:

  1. Sử dụng không gian . Thêm 8 byte cho mỗi chỉ mục. Nhân số đó với 10 chỉ số hoặc hơn và bạn nhận được một sự lãng phí không gian lớn.
  2. Các chỉ mục của cột không hỗ trợ GUID.

(2) Là kẻ giết tôi.

Bây giờ tôi sẽ tạo các khóa của mình như thế này:

yyMMddHH1234567890

Tôi sẽ sử dụng một ngày hàng đầu cộng với giờ và có một phần liên tiếp sau đó. Điều đó cho phép tôi truy vấn phạm vi dữ liệu của mình theo ngày mà không có bất kỳ chỉ số bổ sung nào. Đây là một phần thưởng tốt đẹp cho tôi.

Tôi sẽ tạo ra phần tiếp theo của bigint bằng thuật toán HiLo cho vay chính nó để được phân phối .

Hy vọng một số chuyển này vào tình huống của bạn. Tôi chắc chắn khuyên bạn nên sử dụng bigint.


1
Đánh dấu đây là 'câu trả lời', vì nó phù hợp nhất (và bạn dường như đánh giá cao những gì tôi đang hỏi và tại sao điều này không đơn giản như lần đầu tiên xuất hiện). Tôi nghĩ rằng tôi sẽ sử dụng trình tạo trình tự chia sẻ (sẽ hoạt động tương tự như đề xuất thuật toán HiLo của bạn). Tôi có điều này làm việc trên một hệ thống khác với một vài vấn đề, tôi sẽ phải đưa ra sự phụ thuộc thêm. Ồ tốt Cảm ơn.
Barguast

3

Với một loại INT, bắt đầu từ 1, bạn nhận được hơn 2 tỷ hàng có thể - điều đó là quá đủ cho phần lớn các trường hợp. Với BIGINT, bạn nhận được khoảng 922 triệu (922 với 15 số không - 922'000 tỷ) - đủ cho bạn ??

Nếu bạn sử dụng INT IDENTITYbắt đầu từ 1 và bạn chèn một hàng mỗi giây, bạn cần 66,5 năm trước khi bạn đạt giới hạn 2 tỷ ....

Nếu bạn sử dụng BIGINT IDENTITYbắt đầu từ 1 và bạn chèn một nghìn hàng mỗi giây, bạn cần một khoảng cách đáng kinh ngạc là 292 triệu năm trước khi bạn đạt đến giới hạn 922 triệu triệu ....

Sử dụng 10 triệu hàng mỗi ngày của bạn, điều đó sẽ giúp bạn có đủ số lượng trong khoảng 1'844'674'407'370 ngày ( 1844 tỷ ngày hoặc đánh dấu trên 5 tỷ năm ) dữ liệu - đủ tốt cho nhu cầu của bạn ?

Đọc thêm về nó (với tất cả các tùy chọn có) trong Sách trực tuyến MSDN .


1
Tốc độ chèn 10 triệu hàng mỗi ngày sẽ làm cạn kiệt phạm vi INT trong 200 ngày.
mceda

@mceda: có - tôi có yêu cầu gì nữa không? Nó không làm cạn kiệt BIGINTphạm vi đó một cách nhanh chóng, mặc dù ....
marc_s

Cảm ơn, nhưng như tôi đã nói trong câu hỏi của mình, tôi cần ID trước khi chúng được gửi đến cơ sở dữ liệu. Dữ liệu là quan hệ, vì vậy tôi cần gán khóa chính và khóa ngoài trước khi được sao chép hàng loạt. Nếu không phải như vậy, một IDENTITY BIGINT có thể sẽ hoàn hảo.

2
@Barguast: bạn không thể chèn hàng loạt dữ liệu của mình vào bảng phân tầng (không có danh tính) và sau đó di chuyển dữ liệu từ đó vào các bảng dữ liệu thực tế của bạn bằng cách sử dụng BIGINT IDENTITY?
marc_s

@marc_s: có, phép tính được cung cấp không phù hợp với câu hỏi: "Nếu bạn sử dụng INT IDENTITY bắt đầu từ 1 và bạn chèn một hàng mỗi giây, bạn cần 66,5 năm trước khi bạn đạt giới hạn 2 tỷ".
mceda

2

Tôi khuyên bạn nên sử dụng loại dữ liệu SEQUENCE của BIGINT trong SQL 2012 Điều này linh hoạt hơn nhiều so với IDENTITY với các tùy chọn như cache / nocache, bạn cũng có thể chỉ định phạm vi chuỗi cho hoạt động hàng loạt của mình là sp_ resultence_get_range.


Thật không may, SEQUENCE không được hỗ trợ trên Sql Azure.
Timothy Lee Russell

2

Có phải lý do bạn không thể sử dụng IDENTITY vì đã có các mối quan hệ khóa ngoài giữa các bảng riêng biệt mà bạn đang tải? Và không có chìa khóa tự nhiên nào khác để bạn có thể liên kết chúng trong một hoạt động từ khu vực tổ chức đến khu vực sản xuất? Vì lý do đó, tôi muốn biết thêm một chút về cách chúng hiện được "liên kết" trong hệ thống nguồn trước khi bạn sao chép số lượng lớn? Có phải nhiều hệ thống nguồn chỉ đơn giản sử dụng các chuỗi riêng của chúng và có khả năng cho các chuỗi xung đột khi được đưa vào cơ sở dữ liệu dùng chung không?

ID COMB / kỹ thuật GUID tuần tự là một kỹ thuật mà tôi quen thuộc và có thể thực hiện được bất cứ khi nào bạn thực sự cần sự duy nhất toàn cầu được gán bên ngoài cơ sở dữ liệu - đó thực sự là một nhận dạng hàng có thể sử dụng cả bên trong và bên ngoài cơ sở dữ liệu. Vì lý do đó, trong các môi trường phân tán cao hoặc các tình huống bị ngắt kết nối, đó là một lựa chọn OK

Ngoại trừ nếu bạn thực sự không cần nó, bởi vì sự khác biệt về chiều rộng thêm đó rất có ý nghĩa khi kích thước của dữ liệu tăng lên và các khóa này có trong mọi chỉ mục và các bộ làm việc cho rất nhiều truy vấn.

Ngoài ra, với thế hệ được phân phối, nếu các hàng không thực sự theo thứ tự của cột GUID, thì vấn đề sử dụng khóa này cho khóa chỉ mục cụm (hẹp, tĩnh, tăng) có thể gây ra một số phân mảnh so với phân cụm trên IDENTITY vẫn còn


0

Nói chung, có thể sử dụng OUTPUTmệnh đề INSERTlệnh để có dữ liệu được chèn vào cả hai bảng và liên quan đến trường nhận dạng.

Mã định danh dựa trên dấu thời gian không nên được coi là đáng tin cậy - nó phụ thuộc vào đồng hồ hệ thống, điều này phụ thuộc vào nhiều thứ - từ đồng hồ phần cứng đến dịch vụ đồng bộ hóa thời gian.

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.