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

Подобрете производителността на заявките на SQL Server в големи таблици

Прост отговор:НЕ. Не можете да помогнете на ad hoc заявки в таблица с 238 колони с 50% коефициент на запълване на клъстерирания индекс.

Подробен отговор:

Както посочих в други отговори по тази тема, дизайнът на индекса е едновременно изкуство и наука и има толкова много фактори, които трябва да се вземат предвид, че има малко, ако има такива, твърди и бързи правила. Трябва да имате предвид:обема на DML операции спрямо SELECTs, дискова подсистема, други индекси/задействания на таблицата, разпределение на данни в таблицата, са заявки, използващи условия на SARGable WHERE и няколко други неща, които дори не мога да си спомня правилно сега.

Мога да кажа, че не може да бъде дадена помощ за въпроси по тази тема без разбиране на самата таблица, нейните индекси, тригери и т.н. Сега, когато сте публикували дефиницията на таблицата (все още чакате за индексите, но само дефиницията на таблицата сочи към 99% от проблема) Мога да предложа някои предложения.

Първо, ако дефиницията на таблицата е точна (238 колони, 50% коефициент на запълване), тогава можете почти да игнорирате останалите отговори/съвети тук;-). Съжалявам, че съм по-малко политически тук, но сериозно, това е преследване на дива гъска, без да се знаят подробностите. И сега, когато виждаме дефиницията на таблицата, става доста по-ясно защо една проста заявка би отнела толкова време, дори когато тестовите заявки (актуализация № 1) се изпълняваха толкова бързо.

Основният проблем тук (и в много ситуации с лоша производителност) е лошото моделиране на данни. 238 колони не са забранени, точно както не е забранено наличието на 999 индекса, но също така обикновено не е много разумно.

Препоръки:

  1. Първо, тази таблица наистина трябва да бъде преустроена. Ако това е таблица за склад на данни, тогава може би, но ако не, тогава тези полета наистина трябва да бъдат разделени на няколко таблици, които могат да имат еднакъв PK. Ще имате таблица с главни записи и дъщерните таблици са просто зависима информация, базирана на често асоциирани атрибути и PK на тези таблици е същият като PK на основната таблица и следователно също FK към основната таблица. Ще има връзка 1 към 1 между главните и всички дъщерни таблици.
  2. Използването на ANSI_PADDING OFF е смущаващо, да не говорим за непоследователно в таблицата поради различните добавяния на колони с течение на времето. Не съм сигурен дали можете да поправите това сега, но в идеалния случай винаги ще имате ANSI_PADDING ВКЛЮЧЕНО , или най-малкото да имат една и съща настройка във всички ALTER TABLE изявления.
  3. Помислете за създаване на 2 допълнителни файлови групи:таблици и индекси. Най-добре е да не поставяте вашите неща в PRIMARY тъй като там SQL SERVER съхранява всички свои данни и метаданни за вашите обекти. Вие създавате своята таблица и клъстериран индекс (тъй като това са данните за таблицата) на [Tables] и всички неклъстерирани индекси на [Индекси]
  4. Увеличете коефициента на запълване от 50%. Вероятно това малко число е причината, поради която вашето индексно пространство е по-голямо от пространството ви за данни. Извършването на възстановяване на индекс ще пресъздаде страниците с данни с максимум 4k (от общия размер на страницата 8k), използвани за вашите данни, така че таблицата ви да е разпръсната в широка област.
  5. Ако повечето или всички заявки имат „ER101_ORG_CODE“ в WHERE условие, след което помислете за преместване на това към водещата колона на клъстерирания индекс. Ако приемем, че се използва по-често от "ER101_ORD_NBR". Ако „ER101_ORD_NBR“ се използва по-често, запазете го. Просто изглежда, ако приемем, че имената на полетата означават „OrganizationCode“ и „OrderNumber“, че „OrgCode“ е по-добро групиране, което може да има множество „OrderNumbers“ в себе си.
  6. Незначителен момент, но ако „ER101_ORG_CODE“ винаги е 2 знака, тогава използвайте CHAR(2) вместо VARCHAR(2) тъй като ще запази байт в заглавката на реда, който проследява променливите размери на ширината и събира над милиони редове.
  7. Както други споменаха тук, с помощта на SELECT * ще навреди на производителността. Не само поради това, че изисква SQL Server да връща всички колони и следователно е по-вероятно да извърши клъстерирано индексно сканиране, независимо от другите ви индекси, но също така отнема време на SQL Server, за да отиде до дефиницията на таблицата и да преведе * във всички имена на колони. Трябва да е леко по-бързо, за да посочите всички 238 имена на колони в SELECT списък, но това няма да помогне на проблема със сканирането. Но наистина ли имате нужда от всичките 238 колони едновременно?

Успех!

АКТУАЛИЗИРАНЕ
За пълнота на въпроса "как да подобрим производителността на голяма таблица за ad-hoc заявки", трябва да се отбележи, че макар че няма да помогне за този конкретен случай, АКО някой използва SQL Server 2012 (или по-нова, когато дойде това време) и АКО таблицата не се актуализира, тогава използването на Columnstore Indexes е опция. За повече подробности относно тази нова функция вижте тук:http://msdn.microsoft.com/en-us/library/gg492088.aspx (Смятам, че те са направени така, че да могат да се актуализират, започвайки от SQL Server 2014).

АКТУАЛИЗИРАНЕ 2
Допълнителни съображения са:

  • Активиране на компресиране на клъстерирания индекс. Тази опция стана достъпна в SQL Server 2008, но като функция само за Enterprise Edition. Въпреки това, от SQL Server 2016 SP1 , Компресирането на данни беше налично във всички издания! Моля, вижте страницата на MSDN за компресиране на данни за подробности относно компресията на редове и страници.
  • Ако не можете да използвате компресиране на данни или ако няма да осигури голяма полза за конкретна таблица, тогава АКО имате колона с тип с фиксирана дължина (INT , BIGINT , TINYINT , SMALLINT , CHAR , NCHAR , БИНАРНО , DATETIME , SMALLDATETIME , ПАРИ и т.н.) и доста над 50% от редовете са NULL , след което помислете за активиране на SPARSE опция, която стана достъпна в SQL Server 2008. Моля, вижте страницата MSDN за Използване на редки колони за подробности.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да направя търсене, чувствително към малки и големи букви в клауза WHERE (използвам SQL Server)?

  2. Експортирайте данни от SQL заявка в Excel

  3. Изберете Данни чрез функция с таблично значение в SQL Server

  4. Грешка на SQL Server 111:„...трябва да е първият израз в пакет от заявки“

  5. Създайте свързан сървър между два Docker контейнера, работещи с SQL Server (пример за T-SQL)