Tại sao IDENTITY_INSERT ON chỉ được phép trên một bảng tại một thời điểm?


20

Đó là trường hợp IDENTITY_INSERT chỉ có thể được đặt thành BẬT trong một bảng cơ sở dữ liệu tại một thời điểm, nhưng tại sao? Vì IDENTITYcác cột không phải là duy nhất trên toàn cầu, tôi không thể nghĩ ra bất kỳ tình huống nguy hiểm nào có thể gây ra bằng cách chèn các danh tính vào nhiều bảng cùng một lúc (ít nhất là không nguy hiểm hơn so với nói chung với IDENTITY INSERT).

XÁC NHẬN IDENTITY hiếm khi được sử dụng nhưng lý do cho giới hạn cứng là gì?


1
Răn đe có lẽ, vì vậy nó hiếm khi được sử dụng?
Remus Rusanu

@RemusRusanu đó là những gì tôi đã nghĩ, hoặc là để đảm bảo bạn không vô tình để lại II ON cho nhiều bảng.
Ben Brocka

@Ben tại sao vô tình để nó trên nhiều bảng tệ hơn là vô tình để nó vô tình cho một bảng? Cả hai có thể dẫn đến cùng một loại vấn đề. Tôi thực sự tò mò về câu hỏi của bạn và tôi không nghĩ răn đe là câu trả lời, hoặc chúng tôi sẽ có nhiều hạn chế hơn trong động cơ. Nhưng tôi đồng ý rằng nếu bạn cảm thấy bạn cần phải làm điều này thường xuyên, có lẽ có điều gì đó đáng ngờ.
Aaron Bertrand

@AaronBertrand thì không, như tôi đã ngụ ý trong Q. Không chắc chắn về tính răn đe, vì SQL Server cho phép nhiều thực tiễn xấu khác như đặt tên cột của bạn bằng các từ khóa dành riêng (đôi khi ngay cả khi bạn không sử dụng []!)
Ben Brocka

@Ben đúng không nhất thiết phải dành cho bạn mà cho bất kỳ độc giả nào gặp phải câu hỏi.
Aaron Bertrand

Câu trả lời:


12

Tôi nghĩ rằng nó để làm cho nó khó khăn. Nếu bạn có thể để nó mọi lúc, tại sao thậm chí có một trường danh tính?

Thực tế, có một vài hạn chế:

  • Nó chỉ tồn tại trên kết nối đó
  • Nó chỉ có thể đặt trên một bảng trên mỗi kết nối

Dựa trên các hạn chế liên quan đến kết nối, tôi nghĩ rằng nó chủ yếu để nó không bao giờ vô tình bị BẬT.

Hãy tưởng tượng nếu ai đó bật ID chèn vào một trong các bảng của bạn, thì bạn đã không nhận ra và một thao tác chèn không hợp lệ (thông thường) đã được thực hiện đã phá vỡ tính toàn vẹn của trường ID của bạn?

Các trường ID có thể có các giá trị trùng lặp nếu không có ràng buộc hoặc chỉ mục duy nhất tại chỗ ...


1
+1 Tôi nghĩ rằng điểm cuối cùng của bạn về các bản sao bị bỏ lỡ rất nhiều. Mọi người nghĩ rằng nếu họ thiết lập IDENTITYnó cũng trở thành một ràng buộc duy nhất. Tất nhiên, rất dễ để từ chối, nếu họ cố gắng.
Aaron Bertrand

@AaronBertrand Nhưng một lần nữa, rủi ro ID trùng lặp hoàn toàn giống nhau trên bất kỳ bảng nào có IDENTITY INSERT, tại sao lại giới hạn cứng? Tôi nghĩ rằng thực tế là nó chỉ tồn tại cho kết nối có ý nghĩa hơn nhiều để đề phòng.
Ben Brocka

Tôi đã không đề xuất vấn đề ID trùng lặp là một lý do cho giới hạn cứng.
Aaron Bertrand

6

Tôi đoán đó là một hạn chế do việc thực hiện. Cho phép cài đặt này trên nhiều bảng là một điểm nhấn tiềm năng:

Vì đây là tham số phiên, cho phép kích hoạt cài đặt trên một bảng có nghĩa là cờ đơn giản và id đối tượng của bảng để lưu trữ trên phiên, phía máy chủ. Có thể đây chỉ là một số nguyên duy nhất: 0 nếu không có IDENTITY_INSERT hoạt động và một số mã hóa của cơ sở dữ liệu + objectid cho bảng.

Cho phép tham số được đặt trên nhiều bảng trong một phiên có nghĩa là máy chủ sẽ lưu trữ một danh sách động của các đối tượng đó và kiểm tra nó cho mỗi câu lệnh chèn. Hãy tưởng tượng một phiên kích hoạt tham số cho một nghìn bảng:

  1. Điều này có nghĩa là máy chủ đã phân bổ 1000 mục trong biến phiên
  2. Điều này cũng có nghĩa là máy chủ phải kiểm tra danh sách 1000 mục cho mỗi câu lệnh chèn trong phiên này.

Ngoài ra, tôi nghi ngờ rằng việc đặt id_insert trên có hiệu năng rộng trên hiệu năng trên máy chủ. Trong sybase có một " yếu tố thiết lập ghi nhận dạng ", cho phép lưu giá trị của bộ đếm nhận dạng của một bảng chỉ được lưu trong một thời gian (giá trị được giữ trong bộ nhớ và ghi vào đĩa một lần và tại máy chủ tắt ). SQL Server dựa trên cùng một mã nên có thể có một số tối ưu hóa tương đương, nhưng việc kích hoạt id_insert trên một bảng có thể hạn chế máy chủ lưu giá trị nhận dạng cho mỗi lần chèn, bởi vì nó không thể đảm bảo kích thước khoảng cách tối đa. Vì vậy, nếu một phiên làm cho hiệu suất đạt được trên các phần chèn trong một bảng thì điều này có thể được chấp nhận, nhưng nếu nó có thể tạo ra cú đánh hoàn hảo trên tất cả các bảng auto_increment trên máy chủ ..


+1 Có lẽ một số sự thật ở đây. Tôi không mua đối số kích thước khoảng cách, vì mỗi lần chỉ INSERTcó thể diễn ra một phiên cho một phiên và tôi có thể dễ dàng chèn 10 triệu IDENTITYgiá trị được mã hóa cứng .
Aaron Bertrand

Kích thước khoảng cách có liên quan đến những gì xảy ra trong trường hợp xảy ra sự cố: trên sybase, nếu máy chủ gặp sự cố, danh tính cuối cùng bị mất (trong bộ nhớ), do đó, nó khởi động lại để lại một khoảng trống (xem yếu tố thiết lập ghi nhận dạng)
Olivier S

Vì vậy, trong SQL Server, bạn có gợi ý rằng có điều gì đó khác xảy ra nếu động cơ gặp sự cố trong khi chèn 1.000.000 hàng bằng cột nhận dạng hoặc ghi đè cột nhận dạng bằng 1.000.000 giá trị được mã hóa cứng trong khi SET IDENTITY_INSERTđược bật không? Tôi chỉ đề xuất rằng kích thước khoảng cách không ảnh hưởng đến nhiều bảng khác nhau so với ảnh hưởng đến một bảng.
Aaron Bertrand

dự đoán của tôi - tôi hoàn toàn không có bằng chứng nào về điều này - đó là SET IDENTITY_INSERT trên một bảng buộc ghi vào đĩa tự động trong mỗi lần chèn. Lý do là vì giá trị bạn chèn có thể là bất cứ thứ gì, nên máy chủ không thể xem xét "ok, nếu tôi chỉ ghi vào đĩa một lần trong 1000 hàng, trong trường hợp gặp sự cố, tôi có thể thêm 1000 vào giá trị cuối cùng tôi đã lưu"
Olivier S
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.