sql >> Databáze >  >> RDS >> Sqlserver

Obejít maximální počet sloupců serveru SQL Server 1024 a velikost záznamu 8 kb

Tohle prostě není možné. Viz Uvnitř Storage Engine:Anatomie záznamu

Za předpokladu, že váš stůl je něco takového.

CREATE TABLE T1(
    col_1 varchar(8000) NULL,
    col_2 varchar(8000) NULL,
    /*....*/
    col_999 varchar(8000) NULL,
    col_1000 varchar(8000) NULL
) 

Pak dokonce řádek se všemi NULL hodnoty budou používat následující úložiště.

  • 1 bajtové stavové bity A
  • 1 bajt stavových bitů B
  • Posun počtu sloupců o 2 bajty
  • 125 bajtů NULL_BITMAP (1 bit na sloupec pro 1 000 sloupců)

To je tedy garantovaných 129 již spotřebovaných bajtů (zbývá 7 931).

Pokud má některý ze sloupců hodnotu, která není ani NULL nebo prázdný řetězec, pak také potřebujete místo pro

  • Počet sloupců s proměnnou délkou 2 bajty (zbývá 7 929).
  • Kdekoli mezi 2–2000 bajty pro pole posunu sloupců.
  • Samotná data.

Pole offsetu sloupců spotřebuje 2 bajty na sloupec s proměnnou délkou s výjimkou pokud tento sloupec a všechny následující sloupce mají také nulovou délku. Aktualizace col_1000 by vynutilo použití celých 2000 bajtů při aktualizaci col_1 by použil pouze 2 bajty.

Takže byste mohli naplnit každý sloupec 5 bajty dat a při zohlednění 2 bajtů každého v poli posunu sloupců by to dalo až 7 000 bajtů, což je v rámci zbývajících 7 929.

Data, která ukládáte, jsou však 102 bajtů (51 nvarchar znaků), takže to lze uložit mimo řádek s 24bajtovým ukazatelem na aktuální data zbývající v řádku.

FLOOR(7929/(24 + 2)) = 304

Nejlepším případem by tedy bylo, že byste mohli uložit 304 sloupců této délky dat, a to v případě, že aktualizujete z col_1 , col_2 , ... . Pokud col_1000 obsahuje data, pak je výpočet

FLOOR(5929/24) = 247

Pro NTEXT výpočet je podobný kromě může použít 16bajtový ukazatel což by vám umožnilo vtěsnat data do několika dalších sloupců

FLOOR(7929/(16 + 2)) = 440

Potřeba dodržovat všechny tyto ukazatele mimo řádek pro jakýkoli SELECT v porovnání s tabulkou by to pravděpodobně velmi poškodilo výkon.

Skript pro testování

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)


  1. Obsluha BatchUpdateException pomocí withBatch

  2. mysql - AKTUALIZACE řádku na základě jiných řádků

  3. Líné načítání z databáze, když uživatel posouvá stránku dolů (podobně jako Twitter a Facebook)

  4. Jak získáte dynamický pohled na 12 pracovních dní v Postgresql?