Lý do để tránh các giá trị ID lớn


17

Chúng tôi đang làm việc trên một ứng dụng web, người dùng chưa truy cập được. Sếp của tôi nhận thấy rằng các bản ghi mới được tạo có ID hơn 10 000, mặc dù chúng tôi chỉ có dưới 100 bản ghi trong bảng. Cô cho rằng giao diện web vì một số lý do tạo ra một bản ghi tạm thời gấp 100 lần so với bản ghi thực tế (và xóa chúng) và điều này có thể khiến chúng tôi chạy ra khỏi phạm vi trong vòng vài tháng phát hành.

Tôi không nghĩ cô ấy đúng về nguyên nhân của lạm phát ID (đồng nghiệp có thể trả lời đây là kỳ nghỉ, vì vậy chúng tôi không biết chắc chắn), nhưng hãy giả sử rằng cô ấy là như vậy. Cô ấy nói rằng cô ấy ghét sử dụng cột bigint và cô ấy muốn chúng tôi dừng tự động hóa cột ID và viết mã phía máy chủ chọn số nguyên "không sử dụng" đầu tiên và sử dụng nó làm ID.

Tôi là một sinh viên tốt nghiệp khoa học máy tính với ít kinh nghiệm thực tế, làm đầy vai trò nhà phát triển cơ sở. Cô ấy có nhiều năm kinh nghiệm quản lý tất cả các cơ sở dữ liệu của tổ chức chúng tôi và thiết kế hầu hết chúng. Tôi nghĩ rằng cô ấy không chính xác trong trường hợp này, rằng một bigint ID không có gì phải sợ, và việc bắt chước chức năng DBMS có mùi của một antipotype. Nhưng tôi không tin tưởng vào phán đoán của mình.

Các đối số cho và chống lại từng vị trí là gì? Điều gì xấu có thể xảy ra nếu chúng ta sử dụng một bigint, và những nguy hiểm của việc phát minh lại chức năng tự động bánh xe là gì? Có một giải pháp thứ ba tốt hơn một trong hai? Lý do nào khiến cô ấy muốn tránh lạm phát giá trị ID? Tôi cũng muốn nghe về những lý do thực tế - có thể ID bigint hoạt động trên lý thuyết, nhưng gây đau đầu trong thực tế?

Ứng dụng này dự kiến ​​sẽ không xử lý lượng dữ liệu rất lớn. Tôi nghi ngờ rằng nó sẽ đạt 10 000 hồ sơ thực tế trong vòng vài năm tới.

Nếu nó làm cho bất kỳ sự khác biệt, chúng tôi đang sử dụng máy chủ Microsoft SQL. Ứng dụng này được viết bằng C # và sử dụng Linq cho SQL.

Cập nhật

Cảm ơn bạn, tôi tìm thấy câu trả lời hiện tại và ý kiến ​​thú vị. Nhưng tôi sợ bạn hiểu nhầm câu hỏi của tôi, vì vậy chúng chứa những gì tôi muốn biết.

Tôi không thực sự quan tâm đến lý do thực sự của các ID cao. Nếu chúng ta không thể tự tìm thấy nó, tôi có thể hỏi một câu hỏi khác. Điều tôi quan tâm là hiểu quá trình quyết định trong trường hợp này. Đối với điều này, xin vui lòng giả sử rằng ứng dụng sẽ viết 1000 hồ sơ mỗi ngày, sau đó xóa 9999 trong số chúng . Tôi gần như chắc chắn đây không phải là trường hợp, nhưng đây là những gì ông chủ của tôi tin tưởng khi cô ấy đưa ra yêu cầu của mình. Vì vậy, trong các trường hợp giả định này, những ưu và nhược điểm của việc sử dụng bigint hoặc viết mã riêng của chúng tôi sẽ gán ID (theo cách sử dụng lại ID của các bản ghi đã bị xóa, để đảm bảo không có lỗ hổng)?

Về lý do thực tế, tôi hoàn toàn nghi ngờ rằng điều này là do chúng ta đã từng viết mã để nhập dữ liệu từ cơ sở dữ liệu khác, như một bằng chứng về khái niệm rằng việc di chuyển sau này có thể được thực hiện ở một mức độ nhất định. Tôi nghĩ rằng đồng nghiệp của tôi thực sự đã tạo ra hàng ngàn hồ sơ trong quá trình nhập và sau đó xóa chúng. Tôi phải xác nhận nếu đây thực sự là trường hợp, nhưng nếu có, thậm chí không cần phải hành động.


Xem bài đăng của SM Ahasan Habib tại codeproject.com/Tips/668042/ trên
RLF

Bạn có thể làm rõ? ID mới chỉ đơn giản nhận được giá trị> 10000? Hay là ID mới có khoảng cách 10000? Và có bao nhiêu ID được ước tính là cần thiết trong cuộc sống ứng dụng trong tương lai?
user2338816

1
Liên quan đến việc tìm ID không sử dụng đầu tiên, có một chương về chính xác trong cuốn sách "Các phản mẫu SQL" của Bill Karwin. Vì vậy, có, nó chắc chắn có thể được coi là một antipotype!
Thomas Padron-McCarthy

Câu trả lời:


24

Không nhìn thấy mã, thật khó để nói một cách thuyết phục những gì đang xảy ra. Mặc dù, rất có thể IDENTITYgiá trị đang được lưu trữ, gây ra các khoảng trống về giá trị sau khi SQL Server được khởi động lại. Xem /programming/17587094/identity-column-value-suruptly-jumps-to-1001-in-sql-server để biết một số câu trả lời hay và thông tin về điều đó.

Một INTtrường đơn giản có thể chứa các giá trị lên tới 2.147.483.647. Bạn thực sự có thể bắt đầu giá trị nhận dạng ở -2,147,483,648, cung cấp đầy đủ 32 bit giá trị. 4 tỷ giá trị riêng biệt. Tôi nghi ngờ rất nhiều bạn sẽ dùng hết các giá trị để sử dụng. Giả sử ứng dụng của bạn đang tiêu thụ 1.000 giá trị cho mỗi hàng thực tế được thêm vào, bạn cần tạo gần 12.000 hàng mỗi ngày để hết ID trong 6 tháng với giả sử bạn đã bắt đầu IDENTITYgiá trị ở 0 và đang sử dụng INT. Nếu bạn đang sử dụng BIGINT, bạn sẽ phải đợi 21 triệu thế kỷ trước khi hết giá trị nếu bạn viết 12.000 hàng mỗi ngày, tiêu thụ 1.000 "giá trị" mỗi hàng.

Đã nói tất cả những điều đó, nếu bạn muốn sử dụng BIGINTlàm kiểu dữ liệu trường danh tính, chắc chắn không có gì sai với điều đó. Điều đó sẽ cung cấp cho bạn cho tất cả các mục đích và mục đích, một nguồn cung cấp giá trị vô hạn để sử dụng. Sự khác biệt về hiệu năng giữa INT và BIGINT thực tế không tồn tại trên phần cứng 64 bit hiện đại và rất thích hợp hơn là sử dụng NEWID()để tạo GUID.

Nếu bạn muốn quản lý các giá trị của riêng mình cho cột ID, bạn có thể tạo một bảng khóa và cung cấp một cách thức chống đạn khá tốt bằng cách sử dụng một trong các phương pháp được hiển thị trong câu trả lời cho câu hỏi này: Xử lý truy cập đồng thời vào bảng chính mà không cần bế tắc trong SQL Server

Tùy chọn khác, giả sử bạn đang sử dụng SQL Server 2012+, sẽ sử dụng một SEQUENCEđối tượng để nhận các giá trị ID cho cột. Tuy nhiên, bạn cần định cấu hình chuỗi để không lưu các giá trị bộ đệm. Ví dụ:

CREATE SEQUENCE dbo.MySequence AS INT START WITH -2147483648 INCREMENT BY 1 NO CACHE;

Để trả lời cho nhận thức tiêu cực của sếp về những con số "cao", tôi sẽ nói nó có gì khác biệt? Giả sử bạn sử dụng một INTtrường, với một IDENTITY, trên thực tế bạn có thể bắt đầu IDENTITYtại 2147483647và "tăng" giá trị theo -1. Điều này sẽ hoàn toàn không có sự khác biệt đối với mức tiêu thụ bộ nhớ, hiệu năng hoặc dung lượng ổ đĩa được sử dụng vì số 32 bit là 4 byte, bất kể đó là 0hay 2147483647. 0trong nhị phân là 00000000000000000000000000000000khi được lưu trữ trong INTtrường có chữ ký 32 bit . 214748364701111111111111111111111111111111- cả hai số đều chiếm chính xác cùng một dung lượng, cả trong bộ nhớ và trên đĩa và cả hai đều yêu cầu chính xác cùng một lượng hoạt động CPU để xử lý. Điều quan trọng hơn nhiều là làm cho mã ứng dụng của bạn được thiết kế chính xác hơn là ám ảnh về số thực được lưu trữ trong một trường chính.

Bạn đã hỏi về những ưu và nhược điểm của (a) khi sử dụng cột ID có dung lượng lớn hơn, chẳng hạn như a BIGINT, hoặc (b) lăn giải pháp của riêng bạn để ngăn ngừa khoảng cách ID. Để trả lời những mối quan tâm này:

  1. BIGINTthay vì INTkiểu dữ liệu cho cột được đề cập. Sử dụng một BIGINTyêu cầu gấp đôi dung lượng lưu trữ, cả trên đĩa và trong bộ nhớ cho chính cột. Nếu cột là chỉ mục khóa chính cho bảng có liên quan, thì mỗi và mọi chỉ mục không được nhóm được gắn vào bảng cũng sẽ lưu trữ BIGINTgiá trị, với kích thước gấp đôi INT, một lần nữa cả trong bộ nhớ và trên đĩa. SQL Server lưu trữ dữ liệu trên đĩa trong các trang 8KB, trong đó số lượng "hàng" trên "trang" phụ thuộc vào "chiều rộng" của mỗi hàng. Vì vậy, ví dụ, nếu bạn có một bảng có 10 cột, mỗi cột một INT, bạn sẽ có thể lưu trữ khoảng 160 hàng trên mỗi trang. Nếu những cột đó thay vào đóBIGINTcác cột, bạn chỉ có thể lưu trữ 80 hàng trên mỗi trang. Đối với một bảng có số lượng hàng rất lớn, điều này rõ ràng có nghĩa là I / O được yêu cầu để đọc và viết bảng sẽ gấp đôi trong ví dụ này cho bất kỳ số lượng hàng nhất định. Cấp, đây là một ví dụ khá cực đoan - nếu bạn có một hàng gồm một cột INThoặc một BIGINTcột và một NCHAR(4000)cột duy nhất , bạn sẽ (đơn giản) nhận được một hàng trên mỗi trang, cho dù bạn đã sử dụng một INThoặc một BIGINT. Trong kịch bản này, nó sẽ không tạo ra nhiều khác biệt đáng kể.

  2. Đưa ra kịch bản của riêng bạn để ngăn các khoảng trống trong cột ID. Bạn cần viết mã theo cách xác định giá trị ID "tiếp theo" để sử dụng không xung đột với các hành động khác xảy ra với bảng. Một cái gì đó dọc theo dòng SELECT TOP(1) [ID] FROM [schema].[table]ngây thơ đến trong tâm trí. Điều gì xảy ra nếu có nhiều diễn viên cố gắng viết các hàng mới vào bảng cùng một lúc? Hai diễn viên có thể dễ dàng có được cùng một giá trị, dẫn đến xung đột viết. Giải quyết vấn đề này đòi hỏi phải truy cập tuần tự vào bảng, làm giảm hiệu suất. Đã có nhiều bài báo viết về vấn đề này; Tôi sẽ để nó cho người đọc thực hiện tìm kiếm về chủ đề đó.

Kết luận ở đây là: bạn cần hiểu các yêu cầu của bạn và ước tính đúng cả số lượng hàng và chiều rộng của hàng, cùng với các yêu cầu đồng thời của ứng dụng của bạn. Như thường lệ, Nó phụ thuộc ™.


4
+1 nhưng tôi sẽ không loại bỏ các yêu cầu về không gian của BIGINT. Không quá nhiều cho không gian trên đĩa mà là I / O và không gian bị lãng phí trong bộ nhớ. Bạn có thể bù đắp rất nhiều thứ này bằng cách nén dữ liệu, vì vậy bạn không thực sự cảm thấy gánh nặng của loại BIGINT cho đến khi bạn vượt quá 2 tỷ. Lý tưởng nhất là họ sẽ khắc phục sự cố (tôi ngần ngại gọi đó là lỗi mỗi lần) - trong khi mọi người không nên quan tâm đến các lỗ hổng và trong khi mọi người không nên khởi động lại máy chủ của họ 15 lần một ngày, chúng tôi có cả hai tình huống đó. khá phổ biến, và thường song song.
Aaron Bertrand

3
Điểm rất hợp lệ, Aaron, như thường lệ. Dù sao thì tôi cũng có xu hướng sử dụng INT, vì BIGINT hoàn toàn quá mức cần thiết trừ khi họ đang mong đợi một số lượng lớn hàng.
Max Vernon

Kiểu dữ liệu BIGINT cho cột ID sẽ không ảnh hưởng nhiều đến bộ nhớ trừ khi bạn có hàng trăm nghìn hoặc nhiều hơn trong số chúng trong bộ nhớ cùng một lúc. Thậm chí sau đó, nó có thể là một phần nhỏ của tổng kích thước hàng.
user2338816

2
@ user2338816 đó là điểm chính - nếu bảng trở nên lớn, sẽ có nhiều bộ nhớ. Và vì cột định danh thường là khóa phân cụm, đó cũng là thêm 4 byte cho mỗi hàng trong mỗi chỉ mục. Nó sẽ có vấn đề trong mọi trường hợp? Không. Có nên bỏ qua không? Tuyệt đối không. Dường như không ai có thể lột xác về khả năng mở rộng cho đến khi quá muộn.
Aaron Bertrand

3
Tuy nhiên nếu bạn làm có một kỳ vọng hợp pháp mà bạn có thể cần bigintcó thể bạn sẽ cảm ơn chính mình để quyết định rằng trước chứ không phải là cần để thêm video này vào một bảng với hàng tỉ hàng.
Martin Smith

6

Nhiệm vụ chính cần làm là tìm ra nguyên nhân gốc rễ tại sao giá trị hiện tại lại cao như vậy.

Giải thích hợp lý nhất cho các phiên bản SQL Server trước SQL2012 - nói về việc bạn đang nói về cơ sở dữ liệu kiểm tra - sẽ có một bài kiểm tra tải theo sau là dọn dẹp.

Bắt đầu với SQL2012, lý do có thể xảy ra nhất là do một số lần khởi động lại của SQL Engine (như được giải thích trong liên kết đầu tiên Max cung cấp).

Nếu khoảng cách là do kịch bản thử nghiệm gây ra, không có lý do gì để lo lắng theo quan điểm của tôi. Nhưng để đảm bảo an toàn, tôi sẽ kiểm tra các giá trị nhận dạng trong quá trình sử dụng bình thường của ứng dụng cũng như trước và sau khi khởi động lại động cơ.

Thật là "buồn cười" khi MS tuyên bố rằng cả hai lựa chọn thay thế (hoặc là cờ theo dõi 272 hoặc đối tượng SEQUENCE mới) có thể ảnh hưởng đến hiệu suất.

Đây có thể là giải pháp tốt nhất để sử dụng BIGINT thay vì INT chỉ để ở bên an toàn để trang trải cho "những cải tiến" tiếp theo của MS ...


Có lẽ tôi đã nói sai câu hỏi của mình, nhưng tôi không thực sự quan tâm đến việc tìm ra nguyên nhân. Có khả năng cao là một cái gì đó sẽ không xuất hiện lại (kết quả của quá trình chạy thử) hoặc quyết định thiết kế xấu trong ứng dụng, có thể được giải quyết bên ngoài cơ sở dữ liệu. Vấn đề là để hiểu lý do tại sao một DBA có kinh nghiệm sẽ coi ID cao là xấu, hoặc tệ hơn là quản lý ID của chính chúng ta.
rumtscho

2

Rumtscho, Nếu bạn chỉ tạo 1000 hàng mỗi ngày, có rất ít quyết định - sử dụng loại dữ liệu INT với trường Danh tính và được thực hiện với nó. Toán học đơn giản cho biết nếu bạn cung cấp cho ứng dụng của mình vòng đời 30 năm (không chắc), bạn có thể có 200.000 hàng mỗi ngày và vẫn nằm trong phạm vi số dương của loại dữ liệu INT.

Sử dụng BigInt là quá mức trong trường hợp của bạn, nó cũng có thể gây ra sự cố nếu ứng dụng hoặc dữ liệu của bạn sẽ được truy cập qua ODBC (chẳng hạn như được đưa vào Excel hoặc MS Access, v.v.), Bigint không dịch tốt trên hầu hết các trình điều khiển ODBC sang ứng dụng máy tính để bàn.

Đối với GUIDS, ngoài không gian đĩa phụ và I / O thêm, có một vấn đề lớn là do thiết kế không tuần tự, vì vậy nếu chúng là một phần của chỉ mục được sắp xếp, bạn có thể đoán rằng mọi thao tác chèn sẽ xảy ra yêu cầu chỉ số được nghỉ dưỡng. --Jim


Điểm hay về GUID, trừ khi bạn sử dụng NEWSEQUENTIALID () - Tôi vẫn đồng ý, không có lý do tuyệt vời nào để sử dụng chúng rõ ràng trong câu hỏi này.
Max Vernon

1

Có một khoảng cách giữa các giá trị được sử dụng? Hoặc các giá trị bắt đầu là 10.000 và từ đó trở đi tất cả đang thêm 1? Đôi khi, nếu số này sẽ được trao cho khách hàng, số ban đầu lớn hơn 0, ví dụ 1500, vì vậy khách hàng không nhận ra hệ thống là "mới".

Hạn chế của việc sử dụng bigint thay vì smallint là vì bigint sử dụng "nhiều dung lượng đĩa hơn", khi đọc đĩa bạn đọc ít khối đĩa hơn cho mỗi đĩa. Nếu không gian hàng của bạn nhỏ, thì đây có thể là một nhược điểm, nếu không, chúng không quan trọng lắm. Ngoài ra, điều đó không quan trọng lắm nếu bạn không truy vấn nhiều tài nguyên cùng một lúc và nếu bạn có các chỉ mục thích hợp.

Và như đã nói trong phản hồi khác, nếu bạn lo lắng về việc hết chỉ số, thì bạn không nên lo lắng, smallint có thể xử lý trừ khi bạn có một doanh nghiệp triệu phú. Phát minh ra một cơ chế để "phục hồi id" rất tốn kém và thêm các điểm thất bại và độ phức tạp cho phần mềm.

Trân trọng


2
OP đang thấy những khoảng trống khi khởi động lại dịch vụ. Điều này là do vấn đề này . Ngoài ra tôi không nghĩ rằng một sự nhỏ nhoi là một sự đánh đổi tốt trong ngắn hạn cho công việc cần thiết để khắc phục nó sau này.
Aaron Bertrand

@AaronBertrand thực sự, tôi sợ người khác hiểu nhầm điều này khi họ đề xuất khả năng này. Tôi khá chắc chắn đây không phải là nguyên nhân của những con số cao, nhưng ngay cả khi đó là, tôi đã không cố gắng tìm ra nguyên nhân, nhưng để tìm hiểu những lý lẽ nào có thể có và chống lại các giải pháp được đề xuất. Xem cập nhật của tôi để biết chi tiết.
rumtscho

@rumtscho thực sự câu trả lời này nêu bật một điểm tốt ngay cả khi nó không trực tiếp giải quyết câu hỏi của bạn: "Phát minh ra một cơ chế để 'phục hồi id' rất tốn kém và thêm điểm thất bại và độ phức tạp cho phần mềm."
Doktor J

@DoktorJ Tôi đồng ý với bạn. Tôi là người đã đưa ra câu trả lời :) Chỉ muốn xóa tan sự hiểu lầm, đó là lý do tại sao tôi để lại bình luận đầu tiên của mình.
rumtscho

1

Nếu tôi là sếp của bạn, tôi sẽ quan tâm nhất đến lý do giá trị Id cao bất ngờ ... theo cách tôi thấy, đối với mỗi trong hai kịch bản bạn đã nêu:

  1. NẾU thử nghiệm trước đó đã tăng giá trị nhận dạng - sau đó các nhận xét khác của bạn về số lượng hồ sơ dự kiến ​​cũng sẽ thúc đẩy tôi đề xuất loại khóa nhỏ hơn. Thành thật mà nói tôi cũng sẽ xem xét liệu có thể thiết lập lại trình tự và đánh số lại các bản ghi hiện có nếu thử nghiệm không phù hợp với mục đích sử dụng hiện tại của bảng (hầu hết sẽ xem xét mức độ quá mức này - 'nó phụ thuộc').

  2. NẾU phần lớn các bản ghi được ghi vào bảng sẽ bị xóa ngay sau khi tôi có xu hướng xem xét sử dụng hai bảng thay thế; một bảng tạm thời nơi các bản ghi không được lưu giữ lâu dài và một bảng khác chỉ lưu giữ các bản ghi chúng tôi sẽ tạo vĩnh viễn. Một lần nữa, những kỳ vọng của bạn về số lượng hồ sơ dài hạn gợi ý cho tôi việc sử dụng loại nhỏ hơn cho cột chính của bạn và một vài bản ghi mỗi ngày sẽ khó khiến bạn gặp vấn đề về hiệu suất để 'chuyển' bản ghi từ bảng này sang bảng khác một. Tôi nghi ngờ rằng đó không phải là kịch bản của bạn, nhưng hãy tưởng tượng rằng một trang web mua sắm có thể thích duy trì Rổ / BasketItem và khi một đơn hàng thực sự được đặt, dữ liệu sẽ được chuyển vào bộ Order / OrderItem.

Để tóm tắt; theo ý kiến ​​của tôi, BIGINT không nhất thiết phải sợ hãi, nhưng thực sự lớn không cần thiết cho nhiều kịch bản. Nếu bảng không bao giờ lớn, bạn sẽ không bao giờ nhận ra rằng có quá nhiều sự lựa chọn về loại bạn ... nhưng khi bạn có các bảng có hàng triệu hàng và nhiều cột FK là BIGINT khi chúng có thể nhỏ hơn - thì bạn có thể muốn các loại đã được chọn một cách thận trọng hơn (không chỉ xem xét các cột chính, mà tất cả các cột chính cao nhất và tất cả các bản sao lưu bạn giữ, v.v.). Dung lượng ổ đĩa không phải lúc nào cũng rẻ (xem xét đĩa SAN tại các vị trí được quản lý - tức là không gian đĩa được thuê).

Về bản chất, tôi đang tranh luận để xem xét cẩn thận việc lựa chọn loại dữ liệu của bạn luôn luôn hơn là đôi khi . Bạn sẽ không luôn dự đoán chính xác các mô hình sử dụng, nhưng tôi nghĩ rằng bạn sẽ đưa ra quyết định tốt hơn theo quy tắc sau đó luôn cho rằng 'càng lớn càng tốt'. Nói chung, tôi chọn loại nhỏ nhất có thể chứa phạm vi giá trị hợp lý và bắt buộc và tôi sẽ vui vẻ xem xét INT, SMALLINT và thậm chí TINYINT nếu tôi nghĩ rằng giá trị đó có thể phù hợp với loại đó trong tương lai gần. Tuy nhiên, các loại nhỏ hơn không thể được sử dụng với các cột IDENTITY, nhưng có thể được sử dụng một cách vui vẻ với các bảng tra cứu trong đó các giá trị khóa được đặt thủ công.

Cuối cùng, các công nghệ mà mọi người sử dụng có thể ảnh hưởng đáng kể đến mong đợi và câu trả lời của họ. Một số công cụ có nhiều khả năng gây ra các khoảng trống trong phạm vi, ví dụ như các phạm vi nhận dạng đặt trước cho mỗi quy trình. Ngược lại, @DocSalvager đề xuất một chuỗi có thể kiểm tra kỹ lưỡng dường như phản ánh quan điểm của sếp bạn; Cá nhân tôi chưa bao giờ yêu cầu mức độ thẩm quyền đó - mặc dù quy tắc chung rằng danh tính là tuần tự và thường không có lỗ hổng thường rất hữu ích đối với tôi trong các tình huống hỗ trợ và phân tích vấn đề.


1

Điều gì sẽ là ưu và nhược điểm của việc sử dụng bigint hoặc viết mã riêng của chúng tôi sẽ gán ID (theo cách sử dụng lại ID của các bản ghi đã bị xóa, để đảm bảo không có lỗ hổng)?

Sử dụng bigintnhư một bản sắc và sống với những khoảng trống:

  • đó là tất cả các chức năng được xây dựng
  • bạn có thể chắc chắn rằng nó sẽ hoạt động tốt
  • nó sẽ lãng phí dung lượng vì intvẫn sẽ cung cấp cho bạn dữ liệu khoảng 2 triệu ngày; nhiều trang sẽ phải được đọc và viết; chỉ số có thể trở nên sâu hơn. (Ở các tập này, đây không phải là một mối quan tâm đáng kể).
  • một cột khóa thay thế có nghĩa là vô nghĩa vì vậy khoảng cách là OK. Nếu nó được hiển thị cho người dùng và các khoảng trống được hiểu là đáng kể thì bạn đã làm sai.

Cuộn của riêng bạn:

  • nhóm phát triển của bạn sẽ làm tất cả công việc phát triển và sửa lỗi mãi mãi.
  • bạn chỉ muốn lấp đầy khoảng trống ở đuôi hay ở giữa? Thiết kế quyết định để tranh luận hơn.
  • mỗi lần ghi sẽ phải phát hành các khóa mạnh để ngăn chặn các quy trình đồng thời có được cùng một ID mới hoặc giải quyết xung đột trên thực tế .
  • trường hợp xấu nhất bạn sẽ phải cập nhật mọi hàng trong bảng để đóng các khoảng trống nếu rowid = 1 bị xóa. Điều này sẽ ảnh hưởng đến tính đồng thời và hiệu suất, những gì với tất cả các bản cập nhật khóa ngoài xếp tầng, v.v.
  • lười biếng hoặc háo hức điền vào chỗ trống? Điều gì xảy ra với sự tương tranh trong khi điều này đang xảy ra?
  • bạn sẽ phải đọc ID mới trước khi ghi = tải bổ sung.
  • một chỉ số sẽ là cần thiết trên cột id để tìm khoảng cách hiệu quả.

0

Nếu bạn thực sự lo ngại đạt ngưỡng trên của INT cho PK của mình, hãy cân nhắc sử dụng GUID. Vâng, tôi biết đó là 16 byte so với 4 byte, nhưng đĩa thì rẻ.

Đây là một bài viết tốt về ưu và nhược điểm.


4
+1 vì đây là một giải pháp, nhưng hãy xem nhận xét của Aaron về câu trả lời của Max vì lý do tại sao "đĩa rẻ tiền" không phải là lý do để sử dụng GUID mà không cân nhắc cẩn thận các tùy chọn.
Jack Douglas

1
Đây là một bài viết tốt hơn từ một chuyên gia kiến ​​trúc và chỉ mục SQL Server chứ không phải là một nhà phát triển: sqlskills.com/bloss/kimberly/disk-space-is-cheap
Aaron Bertrand

Ồ, và tất nhiên hãy cẩn thận với việc chia trang từ NEWID ()
Max Vernon

1
Ông chủ của tôi dường như chỉ phản đối các giá trị cao chỉ với lý do họ trông cao. Tôi hy vọng rằng câu hỏi này sẽ cho tôi thấy nhiều sự phản đối có thể hơn, nhưng nếu đây là một trong những tranh luận chính của cô ấy, có lẽ cô ấy sẽ phản ứng thậm chí tiêu cực hơn với GUID.
rumtscho

1
@rumtscho Hãy nói với sếp của bạn rằng một số thay thế chỉ là một số vô nghĩa ("kích thước" của số đó là không liên quan) và những khoảng trống trong chuỗi là tự nhiên và phần lớn là không thể tránh khỏi.
Aaron Bertrand

0

Các khóa chính RDBMS (cột thường được đặt tên 'ID')
Không thể tránh được các khoảng trống trong các cột (trường) tự động RDBMS. Chúng chủ yếu nhằm tạo ra các PK độc đáo. Đối với hiệu suất, các sản phẩm chính phân bổ chúng theo từng đợt, do đó các cơ chế phục hồi tự động cho các trục trặc hoạt động bình thường khác nhau có thể dẫn đến số lượng không được sử dụng. Điều này là bình thường.

Trình tự
không bị gián đoạn Khi bạn cần một số thứ tự không bị gián đoạn, như người dùng thường mong đợi, đó phải là một cột riêng được gán theo chương trình và không nên là PK. Do đó, 1000 bản ghi đó đều có thể có cùng một số trong cột đó.

Tại sao người dùng muốn các chuỗi không bị gián đoạn?
Thiếu số thứ tự là dấu hiệu cơ bản nhất của lỗi được phát hiện trong bất kỳ loại kiểm toán nào. Nguyên tắc "Sổ sách-101" này có mặt khắp nơi. Tuy nhiên, những gì hoạt động cho số lượng nhỏ hồ sơ được duy trì bằng tay, có một vấn đề nghiêm trọng khi áp dụng cho số lượng lớn hồ sơ trong cơ sở dữ liệu ...

Sử dụng lại các giá trị chính cho các bản ghi không liên quan làm mất hiệu lực cơ sở dữ liệu
Sử dụng "số nguyên không sử dụng đầu tiên" đưa ra xác suất rằng tại một thời điểm nào đó trong tương lai, một số sẽ được sử dụng lại cho các bản ghi không liên quan đến bản gốc. Điều đó làm cho cơ sở dữ liệu không đáng tin cậy như là một đại diện chính xác của các sự kiện. Đây là lý do chính mà các cơ chế tự động được thiết kế có chủ đích để không bao giờ sử dụng lại một giá trị.

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.