Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Заобикаляне на ограничението за максимални колони на SQL Server 1024 и размер на записа 8kb

Това просто не е възможно. Вижте вътре в Механизъм за съхранение:Анатомия на запис

Ако приемем, че вашата маса е нещо подобно.

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

След това дори ред с всички NULL стойностите ще използват следното хранилище.

  • 1 байт статус битове A
  • 1 байт статус битове B
  • 2 байта отместване на броя на колоните
  • 125 байта NULL_BITMAP (1 bit на колона за 1000 колони)

Така че това са гарантирани 129 байта, които вече са използвани (остават 7931).

Ако някоя от колоните има стойност, която не е NULL или празен низ, тогава имате нужда и от място за

  • 2 байта брой колони с променлива дължина (оставящи 7929).
  • Някъде между 2 - 2000 байта за масива за отместване на колони.
  • Самите данни.

Масивът за отместване на колони консумира 2 байта на колона с променлива дължина освен ако тази колона и всички следващи колони също са с нулева дължина. И така, актуализиране на col_1000 ще принуди да се използват целите 2000 байта, докато актуализирането на col_1 ще използва само 2 байта.

Така че бихте могли да попълните всяка колона с 5 байта данни и като вземете предвид 2 байта всеки в масива на отместването на колоната, това ще добави до 7000 байта, което е в рамките на оставащите 7929.

Въпреки това данните, които съхранявате, са 102 байта (51 nvarchar символи), така че това може да се съхранява извън реда с 24-байтов указател към действителните данни, оставащи в реда.

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

Така че най-добрият случай би бил, че можете да съхранявате 304 колони с тази дължина на данните и това е, ако актуализирате от col_1 , col_2 , ... . Ако col_1000 съдържа данни, тогава изчислението е

FLOOR(5929/24) = 247

За NTEXT изчислението е подобно с изключение на може да използва 16 байтов указател което би ви позволило да свиете данни в няколко допълнителни колони

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

Необходимостта да се следват всички тези указатели извън реда за всеки SELECT срещу масата вероятно би било силно вредно за производителността.

Скрипт за тестване на това

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Какъв е максималният брой знаци, които nvarchar(MAX) ще съдържа?

  2. Asp.Net 4.0 Съхраняване на сесия в SqlServer

  3. Трябва ли да индексирам битово поле в SQL Server?

  4. Съхранената процедура виси привидно без обяснение

  5. Как да намеря низ в цяла база данни?