2015-03-04 4 views
1

Теперь я прихожу сюда с проблемой «моего» запроса к базе данных. Он работает около 22-25 секунд в «холодной» базе данных, и я отчаянно ищу любой способ его улучшить.SQL Server: запрос выполняется очень медленно (до 20 секунд)

Я хотел бы пропустить любые предложения, связанные с таблицей, просто потому, что я не могу изменить его структуру (слишком плохо). У меня есть то, что мне дано и хорошо ... Я просто пытаюсь найти какое-либо решение для повышения производительности этого запроса. Я знаю, что база данных не разработана хорошо, но на данный момент я ничего не могу с этим поделать, поэтому я соглашусь, если нет возможности улучшить запрос.

SET STATISTICS IO ON; 
SET STATISTICS TIME ON; 
SET STATISTICS PROFILE ON; 

SELECT <STUFF TO SELECT> 
FROM [dbo].[2009_Zlecenia] AS Z 
OUTER APPLY (SELECT TOP 1 M1.DataDo AS 'DataRozladunku', M1.Kod, M1.Miasto, MK1.Skrot FROM [dbo].[MiejscaZaladunkuRozladunku] AS M1 LEFT JOIN [dbo].[Kraje] AS MK1 ON M1.Kraj = MK1.Id WHERE M1.Zlecenie = Z.Id AND M1.Rodzaj = 2 ORDER BY Data DESC) AS MZR 
OUTER APPLY (SELECT TOP 1 M2.DataDo AS 'DataZaladunku', M2.Kod, M2.Miasto, MK2.Skrot FROM [dbo].[MiejscaZaladunkuRozladunku] AS M2 LEFT JOIN [dbo].[Kraje] AS MK2 ON M2.Kraj = MK2.Id WHERE M2.Zlecenie = Z.Id AND M2.Rodzaj = 1 ORDER BY Data ASC) AS MZR1 
OUTER APPLY (Select count(FP1.Id) 'Count' FROM [dbo].[2009_FakturyPrzewoznika] AS FP1 WHERE FP1.ZlecenieId = Z.Id group by FP1.ZlecenieId) AS FP 
OUTER APPLY (SELECT count(FP3.ZlecenieId) 'Count' FROM [dbo].[2009_FakturyPrzewoznika] AS FP3 WHERE FP3.ZlecenieId IN (Select Id FROM [dbo].[2009_Zlecenia] WHERE IdZlecenieNadrzedne <> 0 And IdZlecenieNadrzedne = Z.Id) GROUP BY FP3.ZlecenieId) AS FP2 
OUTER APPLY (SELECT TOP 1 Nr FROM [dbo].[2009_KartyDrogowe] AS KD1 LEFT JOIN [dbo].[ZleceniaKartyDrogowej] AS ZKD1 ON ZKD1.KartaDrogowa = KD1.Id WHERE ZKD1.Zlecenie = Z.Id) AS KD 
OUTER APPLY (Select count(Id) 'Count' FROM [dbo].[2009_Zlecenia] WHERE IdZlecenieNadrzedne <> 0 And IdZlecenieNadrzedne = Z.Id) AS ZP 
LEFT JOIN [dbo].[ZleceniaWalutaObca] AS ZWO ON Z.Id = ZWO.OrderId 
LEFT JOIN [dbo].[Kraje] AS K1 ON Z.TransportZ = K1.Id 
LEFT JOIN [dbo].[Kraje] AS K2 ON Z.TransportDo = K2.Id 
LEFT JOIN [dbo].[Lista] AS L1 ON Z.Status = L1.Id 
LEFT JOIN [dbo].[Uzytkownicy] AS U ON Z.Uzytkownik = U.Id 
LEFT JOIN [dbo].[Oddzialy] AS UO ON U.Oddzial = UO.Id 
LEFT JOIN [dbo].[FakturyZlecen] AS FZ ON FZ.Zlecenie = Z.Id 
LEFT JOIN [dbo].[FakturyZlecen] AS FZ1 ON FZ1.Zlecenie = Z.IdZlecenieNadrzedne 
LEFT JOIN [dbo].[2009_Faktury] AS F1 ON FZ.Faktura = F1.Id 
LEFT JOIN [dbo].[2009_Faktury] AS F2 ON FZ1.Faktura = F2.Id 
LEFT JOIN [dbo].[Firmy] AS FO ON FO.Id = Z.ZleceniodawcaId 
LEFT JOIN [dbo].[Uzytkownicy] AS O1 ON FO.Opiekun1 = O1.Id 
LEFT JOIN [dbo].[Uzytkownicy] AS O2 ON FO.Opiekun2 = O2.Id 
LEFT JOIN [dbo].[Uzytkownicy] AS O3 ON FO.Opiekun3 = O3.Id 
WHERE Z.TypZlecenia = 4 AND Z.Importowane=0 ORDER BY YEAR(Z.DataZlecenia) DESC, Z.Idx DESC, Z.Nr DESC 


SET STATISTICS IO OFF; 
SET STATISTICS TIME OFF; 
SET STATISTICS PROFILE OFF; 

Я бы опубликовал план выполнения, но он довольно большой. Я буду отвечать на любые вопросы относительно этого! :)

Около 80% времени запроса потребляется путем сортировки во внешних предложениях.

Вот статистика из исполнения на "горячей" сервера:

(16467 строк (ы) пострадавших)

Таблица '' Неактивированные. Количество сканирования 0, логического читает 33042, физические чтения 0, упреждающее чтения читает 0, нескладный логическое чтение 0, нескладные физические чтения 0, подбросить упреждающее чтение читает 0.

таблицы «ФИРМА». Сканирование подсчета 0, логическое чтение 50421, физические чтения 0, упреждающее чтение читает 0, нескладехи логический читает 0, нескладные физические чтения 0, подбросить упреждающее чтение читает 0.

таблицу «2009_Faktury». Количество сканирования 0, логического чтение 48577, физический читает 0, упреждающее чтение читает 0, нескладные логические читает 0, нескладные физические чтения 0, подбросить упреждающее чтение читает 0.

таблицу «Worktable». Количество сканирования 0, логический читает 0, физический читает 0, упреждающего чтения читает 0, нескладный логических чтений 0, нескладеха физических чтений 0, подбросить упреждающего чтения читает 0.

таблицу «FakturyZlecen». Количество сканирования 32934, логического чтения 101846, физических чтений 0, упреждающее чтение читает 0, нескладный логический читает 0, нескладный физических чтений 0, подбросить упреждающего чтения читает 0.

таблицу «Oddzialy». Количество сканирования 1, логическое чтение 32935, физический читает 0, упреждающее чтение читает 0, нескладные логические читает 0, нескладные физические чтения 0, подбросить упреждающее чтение читает 0.

таблицы «Лист». Количество сканирования 0, логического чтения 32934, физических чтений 0, упреждающего чтения читает 0, нескладный логический читает 0, подбросить физических чтений 0, подбросить упреждающего чтения читает 0.

таблицу «Kraje». Количество сканирования 2, логического чтения 65874, физических чтений 0, упреждающего чтения читает 0, нескладный логический читает 0, нескладный физических чтений 0, подбросить упреждающего чтения читает 0.

Таблица 'ZleceniaWalutaObca. Число сканирования 1, логическое чтение 0, физическое чтение 0, чтение с чтением 0, логическое считывание логических чисел 0, физическое чтение lob 0, lob чтение с чтением 0.

Таблица «Рабочий стол». Количество сканирования 65420, логического чтения , физический читает 0, упреждающего чтения читает 0, нескладный логический читает 0, подбросить физических чтений 0, подбросить опережающее чтение читает 0.

таблицу «2009_Zlecenia». Сканирование подсчета 32635, логическое чтение 84027, физические чтения 0, упреждающее чтение читает 0, нескладные логические читает 0, нескладные физические чтения 0, подбросить опережающее чтение читает 0.

таблицу «ZleceniaKartyDrogowej». Количество сканирования 1, логическое читает 0, физический читает 0, упреждающее чтение читает 0, нескладные логические читает 0, нескладные физические чтения 0, подбросить упреждающее чтение читает 0.

таблицу «2009_FakturyPrzewoznika». Количество сканирования 318, логического чтения 687, физических чтений 0, упреждающего чтения читает 0, подбросить логических чтений 0, нескладный физических чтений 0, подбросить упреждающего чтения читает 0.

Таблица 'MiejscaZaladunkuRozladunku. Количество сканирования 2, логического чтения 5670, физических чтений 0, упреждающего чтения читает 0, нескладный логический читает 0, подбросить физических чтений 0, подбросить упреждающего чтения читает 0.

SQL Execution сервера Times: процессорное время = 1547 мс, прошедшее время = 1771 мс.

Я выделил «рабочий стол», так как я считаю, что это основная причина такого плохого исполнения.

Любые предложения, которые помогут?

@EDIT

План выполнения здесь:

Overview ExecPlan ExecPlan2 ExecPlan3

+1

План выполнения был бы приятным, хотя, возможно, использовать SQL Sentry Plan Explorer для его отображения? – NickyvV

+1

А где рабочий стол в вашем заявлении? –

+2

Рабочие столы - это временные таблицы, созданные SQL Server на tempdb для выполнения работы tempory - 'ORDER BY',' GROUP BY' и т. Д. См. [MSDN] (https://technet.microsoft.com/en-us/library/ms181037% 2 = sql.105% 29.aspx). Мое предположение с вашим запросом - это серия инструкций 'OUTER APPLY'. Если вы публикуете план выполнения, мы можем увидеть, есть ли какие-либо очевидные узкие места в отношении отсутствующих индексов и т. Д. – Paddy

ответ

3

В плане, как представляется, содержится много index spools, который является оператором, в котором SQL Server создает временный индекс в tempdb. По крайней мере, для этих случаев постоянный индекс должен значительно улучшить производительность.

Выполнение select count(column) SQL Server вычисляет ненулевые значения этого столбца. Когда используется select count(*), вычисляется количество строк, и SQL Server может просто выполнять сканирование индекса для любого индекса.

Хорошо проверить ключевые поисковые запросы из плана, и если есть такие запросы, где фактическое количество выполнения велико, добавление этих столбцов в качестве включенного поля в индекс удаляет поиск ключа. Это имеет дополнительные затраты на вставки/обновления.

Также, разбирая один большой запрос на более мелкие кусочки, вы можете помочь оптимизатору выбрать лучший план. В запросах с несколькими большими таблицами также возможно, что создание плана запроса заканчивается таймаутом, вызывая действительно плохие планы.Это можно увидеть в свойствах первого узла плана запроса («Уровень оптимизации»)

2

Вы определенно должны избавиться от суб выбирает. Они выполняются каждый раз, когда вы повторяете строку. Вы должны попробовать присоединиться к ним, что будет непросто, потому что я вижу, что вы ограничиваете их выбором. 1.

Плохая производительность - это использование подвыборов.

Я не знаю структуру и то, что вы можете сделать одним взглядом, но, возможно, этот простой намек поможет вам в решении.

Рассмотрим один ряд который загружен.

  • заряжаются строки из [2009_Zlecenia]
  • заряжаются ВСЕХ из подвыборки MZR,
  • сортировки MZR
  • промывать все строки, но первый из MZR2
  • Вы нагрузка ВСЕ подзаголовка MZR2,
  • Вы сортируете MZR2
  • вы очищаете Л.Л. линии, но первый из MZR2
  • заряжаются ВСЕ из подвыборки FP1,
  • вам сортировать FP1
  • промывать все строки, но в первую FP1
  • заряжаются ВСЕ из подвыборки FP2 ,
  • вам сортировать FP2
  • промывать все строки, но первый из FP2
  • заряжаются вСЕ переводника выберите KD,
  • сортировки KD
  • промывать все строки, но первые из KD
  • Вы загружаете ALL из подвыборки ЗПА,
  • вам сортировать ZP
  • промывать все строки, но первые от ZP

Вы делаете 10 левых объединений (быстро) только один раз для всех, но думайте о данных, которые загружаются для каждой строки подбором. Они загружаются в каждую строку.

Также Ьгу индексации столбцов, которые вы фильтр для: http://www.1keydata.com/sql/alter-table-add-index.html Индексы будут стимулировать время выполнения на память и потеря жесткого диска.

+1

Согласен, subselects, особенно TOP 1 убивает его производительность .. Я также думаю, что downvoters должны прокомментировать, почему downvote. – DRapp

+0

Добавлено объяснение для процесса sql. – Daniel

+0

Вы советуете любой другой способ сделать это? Я знаю, что я загружаю все данные для каждой строки (я вижу, что на плане выполнения, когда я смотрю на количество выполнения), но я понятия не имею, как это преодолеть;> – user1970395

Смежные вопросы