SELECT K.euclidNo,K.KlinikAdi,k.kisaAdi,
(SELECT COUNT(1) FROM Seanslar AS S
INNER JOIN Faturalar AS F ON F.fatura_id = S.refFatura_id
INNER JOIN BasilmisFaturalar AS BF ON BF.basilmisFatura_id = F.refBasilmisFatura_id
WHERE MONTH(S.tarihi)<MONTH(F.faturaTarihi) AND
S.refKlinik_id = K.klinik_id AND
S.durumuVT = 1 AND
F.faturaTArihi BETWEEN '2009.06.01' AND '2009.06.30' AND
S.refFatura_id = F.fatura_id AND
F.iptalEdenKullanici_id is null
GROUP BY S.refKlinik_id) AS GecmisAydakiSeansSayisi,
(
SELECT kdvDahilToplamTutar FROM BasilmisFaturalar AS BF
INNER JOIN Faturalar AS F ON F.refBasilmisFatura_id = BF.basilmisFatura_id
INNER JOIN Seanslar AS S ON S.refFatura_id = F.fatura_id
WHERE MONTH(S.tarihi)<MONTH(F.faturaTarihi) AND
S.refKlinik_id = K.klinik_id AND
S.durumuVT = 1 AND
S.refFatura_id = F.fatura_id AND
F.faturaTArihi BETWEEN '2009.06.01' AND '2009.06.30' AND
BF.basilmisFatura_id = F.refBasilmisFatura_id AND
F.iptalEdenKullanici_id is null
GROUP by kdvDahilToplamTutar
) as FaturaTutari,
(
SELECT (COUNT(1)*KUA.fiyat) as t FROM Seanslar AS S
INNER JOIN Faturalar AS F ON F.fatura_id = S.refFatura_id
INNER JOIN BasilmisFaturalar AS BF ON BF.basilmisFatura_id = F.refBasilmisFatura_id
INNER JOIN KurumUrunAnlasmalari AS KUA ON KUA.urunAnlasma_id = S.refUrunAnlasma_id
WHERE MONTH(S.tarihi)<MONTH(F.faturaTarihi) AND
S.refKlinik_id = K.klinik_id AND
S.durumuVT = 1 AND
F.faturaTArihi BETWEEN '2009.06.01' AND '2009.06.30' AND
S.refFatura_id = F.fatura_id AND
F.iptalEdenKullanici_id is null
GROUP BY S.refKlinik_id,KUA.fiyat
) AS SeansTutari
FROM Klinikler AS K
WHERE K.refKlinikGrup_id = 1
该查询回答了11秒。我该如何优化呢?它必须回答3或4秒钟。
感谢您的帮助。
答案 0 :(得分:3)
替换子查询:
(
SELECT (COUNT(1)*KUA.fiyat) as t FROM Seanslar AS S
INNER JOIN Faturalar AS F ON F.fatura_id = S.refFatura_id
INNER JOIN BasilmisFaturalar AS BF ON BF.basilmisFatura_id = F.refBasilmisFatura_id
INNER JOIN KurumUrunAnlasmalari AS KUA ON KUA.urunAnlasma_id = S.refUrunAnlasma_id
WHERE MONTH(S.tarihi)<MONTH(F.faturaTarihi) AND
S.refKlinik_id = K.klinik_id AND
S.durumuVT = 1 AND
F.faturaTArihi BETWEEN '2009.06.01' AND '2009.06.30' AND
S.refFatura_id = F.fatura_id AND
F.iptalEdenKullanici_id is null
GROUP BY S.refKlinik_id,KUA.fiyat
)
派生表在klinik_id上加入KLINIKER,性能会大幅提升。
例如:
SELECT K.euclidNo,K.KlinikAdi,k.kisaAdi, IsNull(DeriveOne.ValCount, 0) AS GecmisAydakiSeansSayisi,
....
FROM Klinikler AS K
LEFT JOIN (SELECT S.RefKlinik_id, Count(*) AS ValCount,
FROM Seanslar AS S
INNER JOIN Faturalar AS F ON F.fatura_id = S.refFatura_id
INNER JOIN BasilmisFaturalar AS BF ON BF.basilmisFatura_id = F.refBasilmisFatura_id
WHERE MONTH(S.tarihi) < MONTH(F.faturaTarihi) AND
S.durumuVT = 1 AND
F.faturaTArihi BETWEEN '2009.06.01' AND '2009.06.30' AND
S.refFatura_id = F.fatura_id AND
F.iptalEdenKullanici_id is null
GROUP BY S.refKlinik_id) AS DeriveOne ON DeriveOne.RefKlinik_id = klinik_id
WHERE K.refKlinikGrup_id = 1
答案 1 :(得分:2)
了解问题所在的最佳方法是在查询分析器中运行它,启用show Execution Plan选项。
(这取决于您使用的SQL Server版本,以及是否使用管理工具。)
运行后,查看图片中每个项目的费用属性,看看哪个最高。那是你的瓶颈。 您可以通过添加索引或修改SQL来修复它。
您可能希望查看的另一个属性是查询计划的每个操作中使用的行数,因为这会对性能产生很大影响。
答案 2 :(得分:0)
查询计划和执行计划有所帮助,但它可能因开发环境和生产环境而异。我建议你将查询拆分成各个部分并对其进行性能调整。您可以添加的一些最佳实践是
答案 3 :(得分:0)
这是一种在SQL Server上找到缺失索引的简单方法(我相信2005或更高版本)。列表顶部的索引将产生最高的收益。如果你错过了一个会产生重大影响的东西,它应该会向你跳跃。
SELECT
migs.avg_total_user_cost *
(migs.avg_user_impact / 100.0) *
(migs.user_seeks + migs.user_scans) AS improvement_measure,
'CREATE INDEX ' + UPPER(LEFT (PARSENAME(mid.statement, 1), 32)) + '_IXn'
+ ' ON ' + mid.statement
+ ' (' + ISNULL (mid.equality_columns,'')
+ CASE WHEN mid.equality_columns IS NOT NULL
AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END
+ ISNULL (mid.inequality_columns, '')
+ ')'
+ ISNULL (' INCLUDE (' + mid.included_columns + ')', '')
AS create_index_statement,
migs.*,
mid.database_id,
mid.[object_id]
FROM
sys.dm_db_missing_index_groups mig
INNER JOIN sys.dm_db_missing_index_group_stats migs
ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid
ON mig.index_handle = mid.index_handle
WHERE migs.avg_total_user_cost *
(migs.avg_user_impact / 100.0) *
(migs.user_seeks + migs.user_scans) > 10
ORDER BY
migs.avg_total_user_cost * migs.avg_user_impact *
(migs.user_seeks + migs.user_scans) DESC
答案 4 :(得分:0)
运行此命令:
SET SHOWPLAN_ALL ON
然后运行您的查询。
它将为您提供一个非常详细的列表,列出SQL Server将您的查询转换为结果集的操作。查看输出并尝试了解它的含义。我通常会寻找“SCAN”,这是一个缓慢的部分,我尝试重写它,因此它使用索引。