Dette er simpelthen ikke muligt. Se Inde i Storage Engine:Anatomy of a record
Forudsat at dit bord er noget som dette.
CREATE TABLE T1(
col_1 varchar(8000) NULL,
col_2 varchar(8000) NULL,
/*....*/
col_999 varchar(8000) NULL,
col_1000 varchar(8000) NULL
)
Så endda en række med alle NULL
værdier vil bruge følgende lager.
- 1 byte statusbit A
- 1 byte statusbit B
- 2 bytes kolonneantal offset
- 125 bytes
NULL_BITMAP
(1bit
pr. kolonne for 1.000 kolonner)
Så det er garanteret 129 bytes brugt allerede (efterlader 7.931).
Hvis nogen af kolonnerne har en værdi, der hverken er NULL
eller en tom streng så skal du også have plads til
- 2 bytes variabel længde kolonneantal (efterlader 7.929).
- Hvor som helst mellem 2 - 2000 bytes for kolonneoffset-arrayet.
- Selve dataene.
Kolonneoffset-arrayet bruger 2 bytes pr. kolonne med variabel længde undtagen hvis den kolonne og alle senere kolonner også er nul længde. Så opdaterer col_1000
ville tvinge hele 2000 bytes til at blive brugt, mens opdatering af col_1
ville bare bruge 2 bytes.
Så du kan udfylde hver kolonne med 5 bytes data, og når du tager højde for de 2 bytes hver i kolonneoffset-arrayet, ville det tilføje op til 7.000 bytes, hvilket er inden for de resterende 7.929.
De data, du gemmer, er dog 102 bytes (51 nvarchar
tegn), så dette kan gemmes uden for rækken med en 24 byte pointer til de faktiske data, der er tilbage i rækken.
FLOOR(7929/(24 + 2)) = 304
Så det bedste tilfælde ville være, at du kunne gemme 304 kolonner af disse længdedata, og det er, hvis du opdaterer fra col_1
, col_2
, ...
. Hvis col_1000
indeholder data, så er beregningen
FLOOR(5929/24) = 247
For NTEXT
beregningen ligner, bortset fra den kan bruge en 16 byte pointer
som ville give dig mulighed for at presse data ind i et par ekstra kolonner
FLOOR(7929/(16 + 2)) = 440
Behovet for at følge alle disse off-row pointers for enhver SELECT
mod bordet ville sandsynligvis være yderst skadelig for ydeevnen.
Script til at teste dette
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)