我现在来这里遇到了问题"我的"数据库查询。它在"冷"上执行约22-25秒。数据库,我拼命寻找任何改进它的方法。
我喜欢跳过任何与表格相关的建议,因为我无法改变其结构(太糟糕)。我得到了我已经给予的东西......我只是想找到任何解决方案来改善这个查询的性能。我知道数据库设计不合理,但目前我无法做到这一点,所以如果没有办法改进查询,我会接受。< / p>
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%的查询时间是通过在外部apply子句中进行排序来消耗的。
以下是&#34; hot&#34;执行的统计数据。服务器:
(受影响的16467行)
表&#39; Uzytkownicy&#39;。扫描计数0,逻辑 读取33042,物理读取0,预读取读取0,lob逻辑读取 0,lob物理读取0,lob预读读取0.
表格&#39;坚固&#39;扫描 计数0,逻辑读取50421,物理读取0,预读读取0, lob逻辑读取0,lob物理读取0,lob预读读取0。
表&#39; 2009_Faktury&#39;。扫描计数0,逻辑读取48577,物理 读取0,预读读取0,lob逻辑读取0,lob物理读取 0,lob预读为0.
表&#39;工作台&#39;。扫描计数0,逻辑 读取0,物理读取0,预读取读取0,lob逻辑读取0, lob物理读取0,lob预读读取0.
表&#39; FakturyZlecen&#39;。 扫描计数32934,逻辑读取101846,物理读取0,预读 读取0,lob逻辑读取0,lob物理读取0,lob预读 读数为0.
表&#39; Oddzialy&#39;。扫描计数1,逻辑读取32935,物理 读取0,预读读取0,lob逻辑读取0,lob物理读取 0,lob预读为0.
表&#39; Lista&#39;。扫描计数0,逻辑读取 32934,物理读取0,预读读取0,lob逻辑读取0,lob 物理读取0,lob预读读取0.
表&#39; Kraje&#39;。扫描计数2, 逻辑读取65874,物理读取0,预读读取0,lob逻辑 读取0,lob物理读取0,lob预读读取0.
表 &#39; ZleceniaWalutaObca&#39 ;.扫描计数1,逻辑读取0,物理读取0, 预读读取0,lob逻辑读取0,lob物理读取0,lob 预读读数为0.
表&#39;工作表&#39; 。扫描计数65420,逻辑读取 450989 ,物理读取0,预读读取0,lob逻辑读取0,lob 物理读取0,lob预读读取0.
表&#39; 2009_Zlecenia&#39;。扫描 计数32635,逻辑读取84027,物理读取0,预读取读取 0,lob逻辑读取0,lob物理读取0,lob预读读取0。
表&#39; ZleceniaKartyDrogowej&#39;。扫描计数1,逻辑读取0,物理 读取0,预读读取0,lob逻辑读取0,lob物理读取 0,lob预读为0.
表&#39; 2009_FakturyPrzewoznika&#39;。扫描计数 318,逻辑读取687,物理读取0,预读取读取0,lob 逻辑读取0,lob物理读取0,lob预读读取0.
表 &#39; MiejscaZaladunkuRozladunku&#39 ;.扫描计数2,逻辑读取5670, 物理读取0,预读读取0,lob逻辑读取0,lob 物理读取0,lob预读读取0。
SQL Server执行时间:CPU时间= 1547毫秒,已用时间= 1771 ms。
我突出了&#34;工作台&#34;因为我认为这是表现糟糕的主要原因。
任何有用的建议?
@EDIT
执行计划在这里:
答案 0 :(得分:3)
该计划似乎包含大量index spools
,这是SQL Server在tempdb中构建临时索引的运算符。至少对于那些情况,永久性指数应该会大大提高绩效。
执行select count(column)
SQL Server时计算该列的非空值。使用select count(*)
时,将计算行数,SQL Server可以对任何索引执行索引扫描。
最好从计划中检查密钥查找,如果存在实际执行计数很高的查找,则将这些列添加为索引中的包含字段将删除密钥查找。这会增加插入/更新的成本。
将一个大查询分成更小的部分可以帮助优化器选择更好的计划。在具有多个大表的查询中,查询计划创建也可能在超时中结束,从而导致非常糟糕的计划。这可以在查询计划的第一个节点的属性中看到(&#34;优化级别&#34;)
答案 1 :(得分:2)
你肯定要摆脱子选择。每次迭代一行时都会执行它们。您应该尝试离开加入它们并不容易,因为我看到您通过选择前1来限制它们。
糟糕的表现是使用子选择。
我不知道结构以及您可能一眼就能看到的内容,但也许这个简单的提示可以帮助您解决问题。
让我们考虑加载的一行。
你只为所有人做了10次左连接(快速),但考虑子选择为每一行加载的数据。它们是每排新装的。
同时尝试为您过滤的列编制索引:http://www.1keydata.com/sql/alter-table-add-index.html 索引将增加内存和硬盘丢失的执行时间。