2009-10-29 68 views
19

Tôi có một bảng SQL Server trong sản xuất có hàng triệu hàng, và nó chỉ ra rằng tôi cần phải thêm một cột vào nó. Hoặc, để chính xác hơn, tôi cần phải thêm một trường vào thực thể mà bảng đại diện.Làm thế nào để thêm một cột vào bảng máy chủ sql lớn

Cú pháp này không phải là vấn đề và nếu bảng không có nhiều hàng và không được sản xuất, điều này sẽ dễ dàng.

Thực sự những gì tôi theo sau là quá trình hành động. Có rất nhiều trang web hiện có với các bảng cực lớn và họ phải thêm các trường theo thời gian. Làm thế nào để họ làm điều đó mà không có thời gian chết đáng kể?

Một điều tôi nên thêm, tôi không muốn cột cho phép null, điều này có nghĩa là tôi cần có giá trị mặc định. Vì vậy, tôi cần phải tìm ra cách thêm một cột với giá trị mặc định một cách kịp thời hoặc tôi cần tìm ra cách cập nhật cột vào một thời điểm sau đó và sau đó đặt cột để không cho phép các giá trị rỗng .

Trả lời

23
ALTER TABLE table1 ADD 
    newcolumn int NULL 
GO 

không nên mất nhiều thời gian ... Điều cần một thời gian dài là chèn cột ở giữa các cột khác ... b/c thì động cơ cần tạo bảng mới và sao chép dữ liệu bảng mới.

+6

Bạn biết không, bạn nói đúng. Miễn là cột có giá trị NULL, sau đó nó được thêm khá nhanh. Nhưng nếu tôi nhận được một giá trị mặc định, nó mất một thời gian dài. Vì vậy, vấn đề thực sự tôi cần lập kế hoạch là làm cách nào để thêm giá trị mặc định vào cột. –

+10

Thêm cột và sau đó thực hiện các lô UPDATE tương đối nhỏ để điền cột với giá trị mặc định. Điều đó sẽ ngăn chặn bất kỳ sự chậm đáng chú ý nào. –

+0

Cảm ơn Agent_9191, dường như đó là một cách tiếp cận khá tốt. –

11

Giải pháp thực sự duy nhất cho thời gian hoạt động liên tục là dự phòng.

Tôi thừa nhận câu trả lời của Nestor rằng việc thêm một cột mới sẽ không mất nhiều thời gian trong SQL Server, tuy nhiên, nó vẫn có thể là sự cố không thể chấp nhận được trên hệ thống sản xuất. Một giải pháp thay thế là thực hiện thay đổi trong một hệ thống song song, và sau đó một khi thao tác hoàn tất, hãy trao đổi cái mới cho cái cũ. Ví dụ, nếu bạn cần phải thêm một cột, bạn có thể tạo một bản sao của bảng, sau đó thêm cột vào bản sao đó, và sau đó sử dụng sp_rename() để di chuyển bàn cũ sang một bên và bảng mới vào đúng vị trí.

Nếu bạn có ràng buộc toàn vẹn tham chiếu trỏ đến bảng này, điều này có thể làm cho việc trao đổi thậm chí còn phức tạp hơn. Bạn có thể phải rút ngắn các ràng buộc khi bạn trao đổi các bảng.

Đối với một số loại nâng cấp phức tạp, bạn hoàn toàn có thể sao chép cơ sở dữ liệu trên máy chủ lưu trữ riêng biệt. Khi đã sẵn sàng, chỉ cần trao đổi các mục nhập DNS cho hai máy chủ và thực hiện!

Tôi đã hỗ trợ công ty chứng khoán vào những năm 1990, người chạy ba máy chủ cơ sở dữ liệu trùng lặp mọi lúc. Cách đó cách họ có thể triển khai nâng cấp trên một máy chủ, trong khi giữ lại một máy chủ sản xuất và một máy chủ chuyển đổi . Các hoạt động của họ có quy trình chuẩn xoay vòng ba máy thông qua quá trình sản xuất, chuyển đổi dự phòng và vai trò bảo trì mỗi ngày. Khi họ cần nâng cấp phần cứng, phần mềm hoặc thay đổi lược đồ cơ sở dữ liệu , phải mất ba ngày để tuyên truyền thay đổi thông qua máy chủ của họ, nhưng họ có thể thực hiện việc này không bị gián đoạn . Tất cả cảm ơn về dự phòng.

+2

Bạn bắt kịp các giao dịch bị thiếu trong quá trình bảo trì như thế nào? Sao chép chuẩn? –

+0

Sở giao dịch chứng khoán không cần hoạt động 24/7. Họ đóng chuông. –

+0

Doh :-) Suy nghĩ về cách xử lý cho hệ thống 24/7? –

7

"Thêm cột và sau đó thực hiện theo lô CẬP NHẬT tương đối nhỏ để cư cột với giá trị mặc định. Điều đó sẽ ngăn chặn bất kỳ sự sụt giảm đáng kể"

Và sau đó bạn phải thiết lập cột để NOT NULL sẽ kích hoạt trong một giao dịch lớn. Vì vậy, tất cả mọi thứ sẽ chạy rất nhanh cho đến khi bạn làm điều đó, do đó bạn có thể đã đạt được rất ít thực sự. Tôi chỉ biết điều này từ kinh nghiệm tay đầu tiên.

Bạn có thể muốn đổi tên bảng hiện tại từ X thành Y. Bạn có thể thực hiện việc này bằng lệnh này sp_RENAME '[OldTableName]', '[NewTableName]'. Tạo lại bảng mới dưới dạng X với cột mới được đặt thành NOT NULL và sau đó chèn hàng loạt từ Y đến X và bao gồm giá trị mặc định trong chèn của bạn cho cột mới hoặc đặt giá trị mặc định trên cột mới khi bạn tạo lại bảng X.

Tôi đã thực hiện loại thay đổi này trên một bảng với hàng trăm triệu hàng. Nó vẫn mất hơn một giờ, nhưng nó không thổi bay nhật ký chuyển đổi của chúng tôi. Khi tôi cố gắng chỉ thay đổi cột thành NOT NULL với tất cả dữ liệu trong bảng, nó mất hơn 20 giờ trước khi tôi giết quá trình.

Bạn đã thử nghiệm chỉ việc thêm cột điền dữ liệu vào cột và đặt cột thành NOT NULL?

Vì vậy, cuối cùng tôi không nghĩ rằng có một viên đạn ma thuật.

3

chọn vào bảng mới và đổi tên. Ví dụ: Thêm cột i vào bảng A:

select *, 1 as i 
into A_tmp 
from A_tbl 

//Add any indexes here 

exec sp_rename 'A_tbl', 'A_old' 
exec sp_rename 'A_tmp', 'A_tbl' 

Nên nhanh và không chạm vào nhật ký giao dịch của bạn như chèn theo lô. (Tôi chỉ làm điều này hôm nay với một bảng hàng 70 triệu trong < 2 phút).

Bạn có thể bọc nó trong một giao dịch nếu bạn cần nó là một hoạt động trực tuyến (một cái gì đó có thể thay đổi trong bảng giữa chọn và đổi tên).

+1

Tôi đang đấu tranh để hiểu điều này. Bạn chèn vào 'A_tmp' từ' A_tbl'. Nhưng sau đó bạn đổi tên từ 'A_tbl' thành' A_old' và sau đó đổi tên 'A_old' thành' A_tbl'. Không nên đổi tên lần cuối từ 'A_tmp' thành' A_tbl'? – Junto

+0

@ Vâng, tôi đã sửa nó –

0

Kỹ thuật khác là thêm cột vào bảng có liên quan mới (Giả sử mối quan hệ một-một mà bạn có thể thực thi bằng cách cung cấp chỉ mục FK duy nhất). Sau đó, bạn có thể điền số này theo lô và sau đó bạn có thể thêm tham gia vào bảng này ở bất cứ nơi nào bạn muốn dữ liệu xuất hiện. Lưu ý tôi sẽ chỉ xem xét điều này cho một cột mà tôi sẽ không muốn sử dụng trong mỗi truy vấn trên bảng gốc hoặc nếu chiều rộng bản ghi của bảng ban đầu của tôi đã nhận được quá lớn hoặc nếu tôi đã thêm một số cột.

6

Tôi không muốn cột cho phép null, điều này có nghĩa là tôi cần có giá trị mặc định.

Thêm một cột NOT NULL với một Hạn chế DEFAULT vào một bảng của bất kỳ số lượng hàng (thậm chí hàng tỷ) đã trở thành một khởi đầu rất nhiều dễ dàng hơn trong SQL Server 2012 (nhưng chỉ cho Enterprise Edition) vì chúng cho phép nó được một hoạt động trực tuyến (trong hầu hết các trường hợp) trong đó, đối với các hàng hiện có, giá trị sẽ được đọc từ siêu dữ liệu và không thực sự được lưu trữ trong hàng cho đến khi hàng được cập nhật hoặc chỉ mục nhóm được xây dựng lại.Thay vì diễn giải nữa, đây là phần có liên quan từ trang MSDN cho ALTER TABLE:

Thêm Cột NOT NULL như một hoạt động trực tuyến

Bắt đầu với SQL Server 2012 Enterprise Edition, thêm một NOT NULL cột có giá trị mặc định là hoạt động trực tuyến khi giá trị mặc định là hằng số thời gian chạy . Điều này có nghĩa rằng hoạt động được hoàn thành gần như ngay lập tức bất kể số hàng trong bảng. Điều này là do các hàng hiện có trong bảng không được cập nhật trong quá trình hoạt động; thay vào đó, giá trị mặc định chỉ được lưu trữ trong siêu dữ liệu của bảng và giá trị được tra cứu khi cần trong truy vấn truy cập các hàng này. Hành vi này là tự động; không yêu cầu thêm cú pháp nào để triển khai hoạt động trực tuyến ngoài cú pháp ADD COLUMN. Hằng số thời gian chạy là một biểu thức tạo ra cùng một giá trị tại thời gian chạy cho mỗi hàng trong bảng bất kể định thức của nó. Ví dụ: biểu thức hằng số "Dữ liệu tạm thời của tôi" hoặc hàm hệ thống GETUTCDATETIME() là hằng số thời gian chạy. Ngược lại, hàm NEWID() hoặc NEWSEQUENTIALID() không phải là hằng số thời gian chạy vì một giá trị duy nhất được tạo cho mỗi hàng trong bảng. Thêm một cột NOT NULL với một giá trị mặc định không phải là hằng số thời gian chạy luôn được thực hiện ngoại tuyến và một khóa (SCH-M) độc quyền được mua trong suốt thời gian hoạt động.

Trong khi các hàng hiện tại tham chiếu giá trị được lưu trữ trong siêu dữ liệu, giá trị mặc định được lưu trữ trên hàng cho bất kỳ hàng mới nào được chèn và không chỉ định giá trị khác cho cột. Giá trị mặc định được lưu trữ trong siêu dữ liệu được di chuyển đến hàng hiện tại khi hàng được cập nhật (ngay cả khi cột thực tế không được chỉ định trong câu lệnh UPDATE) hoặc nếu bảng hoặc chỉ mục nhóm được xây dựng lại.

Cột kiểu varchar (max), nvarchar (max), varbinary (max), xml, văn bản, ntext, hình ảnh, HierarchyId, hình học, địa lý, hoặc CLR UDT, không thể được thêm vào trong một hoạt động trực tuyến. Một cột không thể được thêm trực tuyến nếu làm như vậy làm cho kích thước hàng tối đa có thể vượt quá giới hạn 8.060 byte. Cột được thêm dưới dạng hoạt động ngoại tuyến trong trường hợp này.

+0

Điều gì về một cột null SQL Server 2012 phiên bản tiêu chuẩn 14M hàng, đồng thời cao 24x7? Nó sẽ là một thời gian chết đáng chú ý do khóa giản đồ? – Horaciux

+1

@Horaciux Cột 'NULL' thay vì' NOT NULL'? Nếu tôi hiểu chính xác, đó không phải là vấn đề. Đó là siêu dữ liệu chỉ và khá tức thời. Trước khi SQL Server 2012 sắp ra mắt với khả năng thêm một cột 'NULL' ngay lập tức miễn là nó có một giá trị mặc định, cách duy nhất để thêm một cột mà không chặn bất kỳ thứ gì bằng cách thêm nó như là' NULL'. Nhưng sau đó bạn phải điền nó thông qua công việc SQL Agent o làm bộ 3000 hàng cho mỗi UPDATE (để tránh leo thang khóa). Vì vậy, không, bạn không cần phải lo lắng về một cột 'NULL', ít nhất là không có trong kinh nghiệm của tôi. –

Các vấn đề liên quan