Nhanh chóng thay đổi cột NULL thành KHÔNG NULL


11

Tôi có một bảng có hàng triệu hàng và một cột cho phép các giá trị NULL. Tuy nhiên, hiện tại không có hàng nào có giá trị NULL cho cột đó (tôi có thể xác minh điều này khá nhanh bằng một truy vấn). Tuy nhiên khi tôi thực thi lệnh

ALTER TABLE MyTable ALTER COLUMN MyColumn BIGINT NOT NULL;

truy vấn mất mãi mãi tương đối nói. Nó thực sự mất từ ​​10 đến 20 phút, lâu hơn gấp đôi so với việc thêm một ràng buộc kiểm tra. Có cách nào để cập nhật tức thời siêu dữ liệu của bảng cho cột đó không, đặc biệt là vì tôi biết rằng không có hàng nào có giá trị NULL cho cột đó?


2
Không (hoặc ít nhất là không sử dụng các phương pháp được tài liệu / hỗ trợ). Xem tại sao ALTER COLUMN để KHÔNG NULL gây ra sự tăng trưởng tệp nhật ký lớn?
Martin Smith

2
Nó cũng có thể chờ đợi một Sch-Mkhóa khi nó "mãi mãi". Bạn đã nhìn để xem nếu nó đang chờ đợi hoặc bận rộn?
Martin Smith

@MartinSmith Tôi đã làm rõ những gì tôi muốn nói mãi mãi . Tôi đang thử nghiệm điều này trong một môi trường dev không có phiên nào khác đánh vào cơ sở dữ liệu. Cuối cùng nó cũng hoàn thành. Nhưng câu trả lời mà bạn liên kết giải thích tại sao phải mất nhiều thời gian như vậy. Nếu bạn có thể điều chỉnh lại nhận xét của mình dưới dạng câu trả lời, thì tôi sẽ chấp nhận nó.
Joseph Daigle

Câu trả lời:


12

@ câu trả lời của ypercube không quản lý phần này vì siêu dữ liệu chỉ thay đổi.

Thêm ràng buộc với NOCHECKnghĩa là sẽ không cần đọc hàng để xác minh nó và nếu bạn đang bắt đầu từ vị trí mà cột không chứa NULLgiá trị (và nếu bạn biết sẽ không có hàng nào được thêm vào giữa việc kiểm tra và thêm ràng buộc), thì, vì các ràng buộc ngăn chặn NULLcác giá trị được tạo ra từ tương laiINSERT hoặc các UPDATEhoạt động, điều này sẽ hoạt động.

Tuy nhiên, việc thêm các ràng buộc vẫn có thể có tác động đến các giao dịch đồng thời. Các ALTER TABLEsẽ cần phải có được một Sch-Mkhóa đầu tiên. Trong khi chờ đợi, tất cả các truy cập bảng khác sẽ bị chặn như được mô tả ở đây .

Một khi Sch-M khóa được lấy, thao tác sẽ khá nhanh.

Một vấn đề với điều này là ngay cả khi bạn biết cột trong thực tế không có NULLràng buộc nào không được tin cậy bởi trình tối ưu hóa truy vấn, điều đó có nghĩa là các kế hoạch có thể là tối ưu phụ.

CREATE TABLE T (X INT NULL)

INSERT INTO T 
SELECT ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values

ALTER TABLE T WITH NOCHECK
  ADD  CONSTRAINT X_NOT_NULL 
    CHECK (X IS NOT NULL) ; 

SELECT *
FROM T 
WHERE X NOT IN (SELECT X FROM T)

Kế hoạch

So sánh điều này với đơn giản hơn

ALTER TABLE T ALTER COLUMN X INT NOT NULL

SELECT *
FROM T 
WHERE X NOT IN (SELECT X FROM T)

Kế hoạch

Một vấn đề có thể bạn có thể gặp phải khi thay đổi định nghĩa cột theo cách này là nó không chỉ cần đọc tất cả các hàng để xác minh rằng chúng đáp ứng điều kiện mà còn có thể thực sự thực hiện cập nhật nhật ký cho các hàng .

Một ngôi nhà nửa đường có thể là để thêm các ràng buộc kiểm tra WITH CHECK. Điều này sẽ chậm hơn WITH NOCHECKvì nó cần đọc tất cả các hàng nhưng nó cho phép trình tối ưu hóa truy vấn đưa ra kế hoạch đơn giản hơn trong truy vấn ở trên và nó sẽ tránh được sự cố cập nhật có thể xảy ra.


7

Bạn có thể, thay vì thay đổi cột, thêm một CHECKràng buộc bảng với NOCHECKtùy chọn:

ALTER TABLE MyTable WITH NOCHECK
  ADD  CONSTRAINT MyColumn_NOT_NULL 
    CHECK (MyColumn IS NOT NULL) ;

1
Điều này sẽ ngăn các bản cập nhật hoặc chèn trong tương lai tạo ra cột NULLnhưng sẽ không thể được sử dụng bởi trình tối ưu hóa truy vấn.
Martin Smith

@MartinSmith Ồ vâng, tôi vừa đọc câu trả lời và nhận xét trong câu hỏi tương tự: Làm thế nào để bạn thêm Cột KHÔNG NULL vào một bảng lớn trong SQL Server? Xin vui lòng, thêm một câu trả lời với các vấn đề hoặc một giải pháp tốt hơn và tôi sẽ loại bỏ tôi.
ypercubeᵀᴹ

2
Tôi không có giải pháp tốt hơn. Tôi ủng hộ điều này bởi vì nó cung cấp một giải pháp một phần. Nếu tất cả những gì OP muốn làm là ngăn chặn dữ liệu không hợp lệ thì nó sẽ hoạt động (và nên nhanh hơn ALTER COLUMNmột khi Sch-Mkhóa được lấy, điều này không cần phải quét các hàng). Chỉ cần chỉ ra rằng nó không hoàn toàn giống nhau (ví dụ: nếu được sử dụng trong NOT INtruy vấn, kế hoạch sẽ phức tạp hơn)
Martin Smith
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.