Hiệu ứng nào sẽ làm giảm kích thước của cột varchar trên tệp cơ sở dữ liệu?


15

Chúng tôi có một số bảng trong cơ sở dữ liệu của chúng tôi có VARCHAR(MAX)các cột trong đó một VARCHAR(500)(hoặc một cái gì đó nhỏ hơn nhiều so với tối đa) sẽ đủ. Đương nhiên, tôi muốn dọn dẹp chúng, và giảm kích thước xuống mức hợp lý hơn. 'Làm thế nào' để làm điều này tôi hiểu: câu hỏi của tôi là những gì sẽ thay đổi các cột này làm gì cho các trang và phần còn lại trên đĩa? (Có rất nhiều thông tin ngoài kia về những gì xảy ra khi bạn phát triển một cột, nhưng gặp khó khăn khi tìm thông tin về những gì xảy ra khi bạn thu nhỏ một cột.)

Một số bảng có số lượng hàng rất nhỏ, vì vậy tôi không lo lắng về chi phí thay đổi, nhưng một số bảng khá lớn và tôi lo lắng về việc chúng có khả năng được tổ chức lại và gây ra nhiều sự cố / ngừng hoạt động. Trong điều kiện thực tế, tôi chỉ muốn một cách để ước tính một cửa sổ bảo trì. Nói chung, tôi muốn hiểu rõ hơn về cách thức hoạt động của công cụ cơ sở dữ liệu trong trường hợp này.

Cảm ơn trước!

BIÊN TẬP:

Tôi có 20 bảng tôi đang xem, mặc dù chỉ một nửa trong số đó có số hàng lớn hơn 1.000. Lớn nhất có gần một triệu hàng. Người phạm tội tồi tệ nhất là một bảng có 350.000 hàng và bốn VARCHAR(MAX)cột có thể thu nhỏ đến VARCHAR(500)mức.

Câu trả lời:


12

Điều đầu tiên trước tiên: Có bao nhiêu dữ liệu trong bảng? Số lượng hàng và kích thước của bảng?

Thứ hai: Bạn có thể sao lưu và khôi phục bảng này vào máy chủ thử nghiệm và chạy câu lệnh thay đổi để xem tác động (giả sử nó không khả thi do bảng quá lớn để phù hợp với hệ thống không sản xuất)? Tôi luôn thấy rằng thử nghiệm trong môi trường của mình chính xác hơn lời khuyên từ các interweb vì có một số yếu tố có thể ảnh hưởng đến kết quả có thể không được cung cấp trong câu hỏi chỉ vì không biết rằng những yếu tố đó có thể ảnh hưởng đến kết quả.

Thứ ba: tăng kích thước của trường có độ dài thay đổi (giả sử bạn không vượt quá giới hạn 8060 byte) một thao tác dữ liệu meta đơn giản do không có dữ liệu thực tế nào sẽ thay đổi cho hoạt động đó. Mặt khác, NHƯNG, việc giảm kích thước của trường có độ dài thay đổi, thậm chí với thứ gì đó rõ ràng hơn sẽ hoạt động, không phải là thay đổi dữ liệu meta đơn giản vì SQL Server không biết, trước khi quét tất cả các hàng , rằng kích thước mới được yêu cầu là hợp lệ.

Do đó: Có, điều này sẽ khóa bảng trong một khoảng thời gian . Bao nhiêu thời gian Vâng, đây là bài kiểm tra mà tôi vừa làm:

Tôi đã có, từ một số thử nghiệm khác, một bảng có một INT NOT NULLtrường duy nhất và 1 triệu hàng. Tôi đã sao chép nó vào một bảng mới với mục đích thực hiện bài kiểm tra này thông qua:

SELECT *, CONVERT(NVARCHAR(MAX), NEWID()) AS [StringField]
INTO dbo.ResizeTest
FROM dbo.ClusteredUnique;

Bằng cách này, tôi đã bắt đầu với một kịch bản tương tự là có một MAXlĩnh vực (tôi chỉ nhận ra rằng bạn có VARCHARvà tôi đang sử dụng NVARCHAR, nhưng điều đó không làm thay đổi hành vi tôi đang thấy) mà sau đó tôi có thể thay đổi 500. Và nó có dữ liệu trong đó có thể dễ dàng chứa trong vòng 500 ký tự. Điều đó mất một vài phút.

Sau đó tôi chạy:

ALTER TABLE dbo.ResizeTest ALTER COLUMN [StringField] NVARCHAR(500) NULL;

Và điều đó chỉ mất hơn 11 phút.

Tôi vừa chạy lại bài kiểm tra một lần nữa, lần này là bỏ cái [ResizeTest]bàn xuống và thay đổi cả hai NVARCHARđể trở nên công bằng VARCHAR, chỉ để chắc chắn rằng tôi đang so sánh táo với thứ gì đó ít nhất trông giống như một quả táo ;-).

Việc tạo bảng ban đầu mất 20 giây trong khi ALTER TABLEmất 2 phút.

Vì vậy, về mặt ước tính thời gian chết, điều đó thực sự khó thực hiện vì nó dựa trên tốc độ I / O của đĩa, cho dù có hay không bất kỳ hoạt động tăng trưởng tự động nào cần phải xảy ra trên tệp dữ liệu và / hoặc nhật ký giao dịch, v.v. có lẽ là một phần lớn lý do tại sao thử nghiệm đầu tiên của tôi mất 11 phút để thay đổi và lần thứ hai, thậm chí với VARCHARmột nửa kích thước của NVARCHARdữ liệu, chỉ mất 2 phút (tức là các tệp đã được phát triển trước tại thời điểm đó). Tuy nhiên, bạn nên nhớ rằng bài kiểm tra của tôi đang chạy trên máy tính xách tay của tôi không phải là đĩa nhanh nhất, nhưng nó cũng chỉ là 1 triệu hàng gồm 2 cột nhỏ (22 hoặc hơn byte mỗi hàng).

Và vì bạn đã hỏi nó sẽ làm gì với các trang dữ liệu, đây là câu trả lời của bạn. Tôi đã làm một sp_spaceusedsau khi tạo bảng, sau khi làm ALTER COLUMNvà sau khi làm ALTER TABLE dbo.ResizeTest REBUILD;. Kết quả (các số sau được dựa trên thử nghiệm thứ hai bằng cách sử dụng VARCHAR, không phải thử nghiệm đầu tiên sử dụng NVARCHAR):

After initial table creation:        526,344 KB
After ALTER COLUMN VARCHAR(500):   1,031,688 KB  <--- !! Yikes!!
After ALTER REBUILD:                 526,472 KB

Nếu bạn lo lắng về việc cần phải duy trì hoạt động trong thời gian ngắn nhất có thể, hãy xem một bài viết mà tôi đã viết về việc đó: Tái cấu trúc 100 triệu hàng (hoặc nhiều hơn) Bảng trong giây. SRSLY! (yêu cầu đăng ký miễn phí).


2
Vì vậy, tôi đã sao chép bảng tệ nhất vào thể hiện cục bộ của mình (ví dụ, đĩa chậm hơn và 1/3 lõi). Tôi chỉnh sửa ALTERtừng cột liên tiếp - mỗi hành động mất ít hơn một giây. Vào thời điểm chúng được thực hiện, bảng đã tăng gấp đôi kích thước, nhưng một khi tôi đã thực hiện REBUILD(cũng là thao tác phụ thứ hai), bảng trở lại kích thước ban đầu.
nateirvin

@nateirvin Điều đó thật tốt khi nghe. Bạn có thể có thể tăng tốc ALTER TABLEthao tác bằng cách thực hiện tất cả các trường trong một lần chụp, tách từng cột bằng dấu phẩy. Nếu giao dịch quá lớn thì hãy chia bảng thành 2 câu lệnh ALTER của một nửa số cột mỗi cột. Và tùy thuộc vào mức độ lớn của bảng, bạn thậm chí có thể thực hiện REBUILD giữa mỗi câu lệnh ALTER. Một cái gì đó để chơi với. Ngoài ra, hãy nhớ rằng hoạt động có thể sẽ có một khóa lược đồ trong thời gian sẽ chặn tất cả quyền truy cập vào bảng.
Solomon Rutzky

1
Tôi đã làm ALTERriêng từng cái để tôi có thể theo dõi sự thay đổi kích thước giữa mỗi cái, nhưng chắc chắn là tốt để biết. Cảm ơn!
nateirvin

1

Từ những gì tôi đã thu thập được khi chạy câu lệnh thay đổi không nên mất nhiều thời gian miễn là tại bàn không bị khóa bởi một quy trình khác. Theo gbn, đó chỉ là một thay đổi siêu dữ liệu: /programming/7261909/is-it-bad-to-use-alter-table-to-resize-a-varchar-column-to-a-larger -kích thước

Ngoài ra, về cách nó được lưu trữ, có vẻ như SQL Server đã lưu trữ dữ liệu varchar trong một trang 8k cho đến khi nó lấp đầy toàn bộ một trang, tại thời điểm này, nó thay thế nó bằng một con trỏ và lưu trữ nó dưới dạng BLOB.

Tôi giả sử rằng khi bạn thay đổi độ dài, bạn sẽ không cắt bớt bất kỳ hồ sơ nào. Nếu vậy, thì tối đa dữ liệu mà bạn đang chuyển đổi thành varchar (500) phải dài tối đa 502 byte và không nên có một con trỏ.

Vì vậy, câu chuyện dài ngắn, không nhiều nên thay đổi miễn là bạn không cắt bớt bất kỳ dữ liệu nào.


5
Điều này là hoàn toàn không chính xác. Tôi sẽ không downvote vì bạn thực sự đã thử nó (nhiều hơn một số người làm, vì vậy cảm ơn vì đã làm điều đó), nhưng bạn cần kiểm tra điều này ở quy mô. Câu trả lời bạn liên kết là về việc tăng kích thước, không giảm. Đó là hai hoạt động rất khác nhau.
Solomon Rutzky
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.