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

Проблеми с производителността на параметъра на табличната стойност

Ако TVP са „забележимо по-бавни“ от другите опции, тогава най-вероятно не ги прилагате правилно.

  1. Не трябва да използвате DataTable, освен ако приложението ви го използва извън изпращането на стойностите към TVP. Използване на IEnumerable<SqlDataRecord> интерфейсът е по-бърз и използва по-малко памет, тъй като не дублирате колекцията в паметта само за да я изпратите в DB. Имам това документирано на следните места:
  2. Не трябва да използвате AddWithValue за SqlParameter, въпреки че това вероятно не е проблем с производителността. Но все пак трябва да е:

    SqlParameter tvp = com.Parameters.Add("data", SqlDbType.Structured);
    tvp.Value = MethodThatReturnsIEnumerable<SqlDataRecord>(MyCollection);
    
  3. TVP са таблични променливи и като такива не поддържат статистика. Което означава, че те съобщават, че имат само 1 ред на оптимизатора на заявки. Така че във вашата процедура или:
    • Използвайте прекомпилиране на ниво израз на всякакви заявки, използващи TVP за нещо различно от обикновен SELECT:OPTION (RECOMPILE)
    • Създайте локална временна таблица (т.е. единичен # ) и копирайте съдържанието на TVP във временната таблица
    • Можете да опитате да добавите клъстерен първичен ключ към дефинирания от потребителя тип таблица
    • Ако използвате SQL Server 2014 или по-нов, можете да опитате да използвате In-Memory OLTP / таблици, оптимизирани за памет. Моля, вижте:По-бърза временна таблица и променлива на таблица чрез използване на оптимизация на паметта

Относно защо виждате:

insert into @data ( ... fields ... ) values ( ... values ... )
-- for each row
insert into @data ( ... fields ... ) values ( ... values ... )

вместо:

insert into @data ( ... fields ... ) 
values ( ... values ... ),
       ( ... values ... ),

АКО това наистина се случва, тогава:

  • Ако вмъкванията се извършват в рамките на транзакция, тогава няма реална разлика в производителността
  • По-новият синтаксис на списък със стойности (т.е. VALUES (row1), (row2), (row3) ) е ограничен до нещо като 1000 реда и следователно не е жизнеспособна опция за TVP, които нямат това ограничение. ОБАЧЕ, това не е вероятно причината да се използват отделни вмъквания, като се има предвид, че няма ограничение, когато правите INSERT INTO @data (fields) SELECT tab.[col] FROM (VALUES (), (), ...) tab([col]) , което документирах тук:Максимален брой редове за конструктора на стойността на таблицата . Вместо това...
  • Причината най-вероятно е, че извършването на отделни вмъквания позволява поточно предаване на стойностите от кода на приложението в SQL Server:
    1. използване на итератор (т.е. IEnumerable<SqlDataRecord> отбелязано в #1 по-горе), кодът на приложението изпраща всеки ред, както е върнат от метода, и
    2. конструиране на VALUES (), (), ... списък, дори ако правите INSERT INTO ... SELECT FROM (VALUES ...) подход (който не е ограничен до 1000 реда), който пак ще изисква изграждане на цялата VALUES списък, преди да изпратите всяко на данните в SQL Server. Ако има много данни, това ще отнеме повече време за конструиране на супер дългия низ и ще заеме много повече памет, докато го прави.

Моля, вижте също тази бяла книга от екипа за консултации на клиенти на SQL Server:Максимизиране на пропускателната способност с TVP



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Проверка на синтаксиса на всички съхранени процедури?

  2. Настройка на SQL Server Reporting Services

  3. Най-бързият начин за прехвърляне на данни от таблици на Excel към SQL 2008R2

  4. Преименувайте SA акаунта в SQL Server (пример за T-SQL)

  5. Как да инсталирате SQL Server Manager Studio (SSMS) - SQL Server / TSQL урок, част 1