Запрос SQL Server повышает производительность на связанном сервере

#sql #sql-server #performance #select #sql-like

#sql #sql-server #Производительность #выберите #sql-подобный

Вопрос:

Как я могу улучшить следующий запрос SQL Server?

 SELECT SUM(Qty) 
FROM Products
WHERE Type = 'SODA'
AND (Code LIKE 'A5%'
OR Code IN('DHA2','JHU8','KML2','LQA1','ZSX2')) 
  

Выполнение занимает много времени.

Заранее спасибо.

Я получаю данные из базы данных DB2 через связанный сервер. Я не могу создавать индексы только для чтения.

 Id   int
Name nvarchar(100)
Type nvarchar(100)
Code nvarchar(100)
Qty  int
  

Комментарии:

1. какова ваша схема таблицы (типы столбцов, индексы)?

2. индексируются ли тип и код?

3. Есть ли индекс в коде столбца? В противном случае оператор Like принудительно выполнит последовательное чтение. Создание плана объяснения поможет определить, где проблема с производительностью.

4. Можете ли вы опубликовать план выполнения вместе с любыми индексами, которые у вас уже есть. Как бы то ни было, если вы запустите этот запрос в среде SQL Server Management Studio с включенной опцией «Включить фактический план выполнения», SQL Server предложит индексы, которые улучшат ваш запрос. Вероятно, это будет гораздо полезнее, чем любой приведенный здесь ответ, поскольку мы ничего не знаем о вашей таблице, только то, что она содержит как минимум 3 столбца (кол-во, тип и код).

5. Вероятный ответ — создать следующий индекс CREATE NONCLUSTERED INDEX IX_Products_Code ON Products (Code) INCLUDE (Qty) WHERE Type = 'SODA' — однако этот индекс полностью ориентирован на этот запрос и, вероятно, не сильно поможет в других ваших запросах.

Ответ №1:

Сначала попробуйте создать индекс на products(type, code, qty) . Это может значительно повысить производительность.

Затем, если это не сработает, попробуйте переписать запрос как:

 select sum(qty)
from ((select qty
       from products
       where type = 'SODA' and
             code like 'A5%'
      ) union all
      (select qty
       from products
       where type = 'SODA' and
             code IN ('DHA2','JHU8','KML2','LQA1','ZSX2'))
      )
     ) t;
  

Это может показаться более сложным, но иногда or мешает оптимизации запросов.

Комментарии:

1. Человек, который спросил, заявил, что он не может создавать индексы. Так что это неправильный ответ, потому что разделение запроса на два запроса к таблице без индексов приведет к двум полным сканированиям таблицы вместо одного. Таким образом, запрос будет выполняться еще медленнее.

2. @Baltico . , , Если вы посмотрите на историю редактирования, вы увидите, что этот комментарий был вставлен в вопрос после завершения этого ответа.

3. Спасибо, Гордон, я не знал, что это возможно. Конечно, без этого ограничения добавление индексов будет лучшим советом.

Ответ №2:

Это запрос связанного сервера. Вы не указываете, как вы его выполняете, поэтому я предполагаю, что он использует имя связанного сервера в FROM . Если вы посмотрите на план запроса, все, что вы увидите, это Удаленный запрос -> Скалярный компьютер -> Выбрать. Это в основном означает, что все данные, которые вы хотите вычислить, копируются в базу данных tempDB, а затем вычисляются.

Если вы выполняете запрос как EXEC at или OPENQUERY, запрос выполняется удаленно, тогда единственное, что нужно вернуть, это результат.

Попробуйте это:

 select *
from 
openquery(LinkedServerName, '   
SELECT SUM(Qty) Total
FROM Products
WHERE Type = ''SODA''
AND (Code LIKE ''A5%''
OR Code IN(''DHA2'',''JHU8'',''KML2'',''LQA1'',''ZSX2'')) ')
  

Ответ №3:

Поскольку вы используете связанный сервер, а также проводите сравнение строк, я почти уверен, что ваша низкая производительность связана с тем, что SQL Server должен перенести всю таблицу Product из базы данных DB2 в локальную копию, а затем сравнить строки в соответствии с вашими текущими настройками сортировки. Видите ли, сравнение строк может иметь разные результаты при разных параметрах сортировки и в разных системах баз данных. При соединении между базами данных Microsoft SQL Servers вы можете включить совместимость параметров сортировки, чтобы при выполнении запроса он доверял решению связанного сервера о сравнении и сортировке строк. Я не знаю, возможна ли совместимость параметров сопоставления между Microsoft SQL Server и DB2. Таким образом, решением проблемы будет использование OPENROWSET вместо связанного сервера.

Что-то вроде этого:

  SELECT * FROM OPENROWSET 
 ('DB2OLEDB',Netlib=SNA;NetAddr=;NetPort=;RemoteLU=OLYMPIA;LocalLU=LOCAL;ModeName=QPCSUPP;User ID=WNW3XX;Password=WNW3XX;InitCat=OLYMPIA;Default Schema=WNW3XX;PkgCol=WNW3XX;TPName=;Commit=YES;IsoLvl=NC;AccMode=;CCSID=37;PCCodePage=1252;BinAsChar=NO;Data Source=Sample',
 'SELECT SUM(Qty) 
FROM Products
WHERE Type = ''SODA''
AND (Code LIKE ''A5%''
OR Code IN(''DHA2'',''JHU8'',''KML2'',''LQA1'',''ZSX2'')) ' )
  

Дополнительные сведения см. в разделе связанный сервер с DB2 с использованием поставщика Microsoft OLE DB для DB2

И в OPENROWSET (Transact-SQL)

Ответ №4:

Если это займет так много времени, я предлагаю вам создать таблицу с такой же структурой, затем создать несколько полезных индексов, а затем выполнить запрос к этой локальной таблице:

 DELETE FROM Products

INSERT INTO Products
SELECT * FROM RemoteServer.database_name..Products

SELECT SUM(Qty) 
FROM Products
WHERE Type = 'SODA'
AND (Code LIKE 'A5%'
OR Code IN('DHA2','JHU8','KML2','LQA1','ZSX2'))