Điều này đơn giản là không thể. Xem Bên trong Công cụ lưu trữ:Giải phẫu hồ sơ
Giả sử bảng của bạn giống như thế này.
CREATE TABLE T1(
col_1 varchar(8000) NULL,
col_2 varchar(8000) NULL,
/*....*/
col_999 varchar(8000) NULL,
col_1000 varchar(8000) NULL
)
Sau đó, ngay cả một hàng có tất cả NULL
các giá trị sẽ sử dụng bộ nhớ sau.
- Các bit trạng thái 1 byte A
- Các bit trạng thái 1 byte B
- Độ lệch số lượng cột 2 byte
- 125 byte
NULL_BITMAP
(1bit
mỗi cột cho 1.000 cột)
Vì vậy, đó là 129 byte được đảm bảo đã được sử dụng hết (còn lại 7.931).
Nếu bất kỳ cột nào có giá trị không phải là NULL
hoặc một chuỗi trống thì bạn cũng cần không gian cho
- Số lượng cột có độ dài thay đổi 2 byte (còn lại 7,929).
- Bất kỳ nơi nào trong khoảng từ 2 - 2000 byte đối với mảng bù cột.
- Bản thân dữ liệu.
Mảng bù cột sử dụng 2 byte cho mỗi cột có độ dài thay đổi ngoại trừ nếu cột đó và tất cả các cột sau đó cũng có độ dài bằng không. Vì vậy, cập nhật col_1000
sẽ buộc toàn bộ 2000 byte được sử dụng trong khi cập nhật col_1
sẽ chỉ sử dụng 2 byte.
Vì vậy, bạn có thể điền vào mỗi cột 5 byte dữ liệu và khi tính đến 2 byte mỗi cột trong mảng bù cột sẽ cộng tới 7.000 byte nằm trong 7.929 còn lại.
Tuy nhiên, dữ liệu bạn đang lưu trữ là 102 byte (51 nvarchar
ký tự) để điều này có thể được lưu trữ ngoài hàng với con trỏ 24 byte đến dữ liệu thực tế còn lại trong hàng.
FLOOR(7929/(24 + 2)) = 304
Vì vậy, trường hợp tốt nhất sẽ là bạn có thể lưu trữ 304 cột dữ liệu độ dài này và đó là nếu bạn đang cập nhật từ col_1
, col_2
, ...
. Nếu col_1000
chứa dữ liệu thì phép tính là
FLOOR(5929/24) = 247
Đối với NTEXT
cách tính tương tự ngoại trừ nó có thể sử dụng con trỏ 16 byte
điều này sẽ cho phép bạn đưa dữ liệu vào một vài cột bổ sung
FLOOR(7929/(16 + 2)) = 440
Sự cần thiết phải tuân theo tất cả các con trỏ hàng tắt này cho bất kỳ SELECT
nào chống lại bảng có thể sẽ rất bất lợi cho hiệu suất.
Tập lệnh để kiểm tra điều này
DROP TABLE T1
/* Create table with 1000 columns*/
DECLARE @CreateTableScript nvarchar(max) = 'CREATE TABLE T1('
SELECT @CreateTableScript += 'col_' + LTRIM(number) + ' VARCHAR(8000),'
FROM master..spt_values
WHERE type='P' AND number BETWEEN 1 AND 1000
ORDER BY number
SELECT @CreateTableScript += ')'
EXEC(@CreateTableScript)
/* Insert single row with all NULL*/
INSERT INTO T1 DEFAULT VALUES
/*Updating first 304 cols succeed. Change to 305 and it fails*/
DECLARE @UpdateTableScript nvarchar(max) = 'UPDATE T1 SET '
SELECT @UpdateTableScript += 'col_' + LTRIM(number) + ' = REPLICATE(1,1000),'
FROM master..spt_values
WHERE type='P' AND number BETWEEN 1 AND 304
ORDER BY number
SET @UpdateTableScript = LEFT(@UpdateTableScript,LEN(@UpdateTableScript)-1)
EXEC(@UpdateTableScript)