[英]Optimize sql query
我有一個需要1:20分鍾執行的SQL。 它處理一年的數據,但是即使如此,我仍感覺花費了太長時間。 我已將EXISTS的IN用法更改為另一個查詢的推薦值(在這種情況下,優化還不夠:S),您還有其他建議來對其進行優化嗎?
select gd.descripcion,count(gd.descripcion) as total
from diagnosticos d,gruposdiagnosticos gd, ServiciosMedicos s, pacientes p,Actos a,historias h
where p.codigo=h.codpaciente and p.codigo=a.codpaciente and p.codigo=h.codpaciente and p.codigo=s.codpaciente and h.codpaciente=a.codpaciente and h.codpaciente=s.codpaciente and a.codpaciente=s.codpaciente and h.numhistoria=a.numhistoria and h.numhistoria=s.numhistoria and a.numacto=s.numacto and h.codseccion=a.codseccion and a.codseccion=s.codseccion and d.codigo=s.codDiagnostico and gd.codigo=d.codgrupo
and p.codcompañia ='35' and a.codseccion ='18'
and (CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >='20090101')
and (CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) <='20091231')
and h.modo ='Urgente'
and datename(weekday,a.fecatencion)!= 'Sabado'
and datename(weekday,a.fecatencion)!= 'Domingo'
AND NOT EXISTS (select * from diasfestivos af where (datename(d,a.fecatencion) + datename(m,a.fecatencion))=(datename(d,af.fechafestiva) + datename(m,af.fechafestiva)) AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >= af.fechafestiva AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) < af.fechafestiva + 1 and datepart(yy,af.fechafestiva)='1990')
AND NOT EXISTS (SELECT * FROM diasfestivos af WHERE CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >= af.fechafestiva AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) < af.fechafestiva + 1 AND datepart(yy,af.fechafestiva)!=1990)
group by gd.descripcion order by gd.descripcion
根據您的建議更改查詢將使查詢在50秒內完成,謝謝,但是應該有一種方法可以減少查詢的次數...查詢現在是:
select gd.descripcion,count(gd.descripcion) as total
from diagnosticos d,gruposdiagnosticos gd, ServiciosMedicos s, pacientes p,Actos a,historias h
where p.codigo=h.codpaciente and p.codigo=a.codpaciente and p.codigo=h.codpaciente and p.codigo=s.codpaciente and h.codpaciente=a.codpaciente and h.codpaciente=s.codpaciente and a.codpaciente=s.codpaciente and h.numhistoria=a.numhistoria and h.numhistoria=s.numhistoria and a.numacto=s.numacto and h.codseccion=a.codseccion and a.codseccion=s.codseccion and d.codigo=s.codDiagnostico and gd.codigo=d.codgrupo
and p.codcompañia ='35' and a.codseccion ='18'
and a.fecAtencion +1 >'20090101'
and a.fecAtencion -1 <'20091231'
and h.modo ='Urgente'
and DATEPART(dw,a.fecatencion)!=6
and DATEPART(dw,a.fecatencion)!=7
AND NOT EXISTS (select * from diasfestivos af where (datename(d,a.fecatencion) + datename(m,a.fecatencion))=(datename(d,af.fechafestiva) + datename(m,af.fechafestiva)) AND a.fecAtencion +1 > af.fechafestiva AND a.fecAtencion -1 < af.fechafestiva and datepart(yy,af.fechafestiva)='1990')
AND NOT EXISTS (SELECT * FROM diasfestivos af WHERE a.fecAtencion +1 > af.fechafestiva AND a.fecAtencion -1 < af.fechafestiva AND datepart(yy,af.fechafestiva)!=1990)
group by gd.descripcion order by gd.descripcion
我有2個存在的部分,因為我有兩種類型的節日日期。 特定於當前年份的年份和其他每年適用的年份(因此,我將其像1990年12月25日這樣插入)
最終,我發現了這一部分的問題。
其中datename(d,a.fecatencion)+ datename(m,a.fecatefcion))=(datename(d,af.fechafestiva)+ datename(m,af.fechafestiva))
有人知道更好的方法嗎? (比較tsql中省略日期的2個日期時間)
between ... and
語法between ... and
使用簡單的比較 datename(weekday,a.fecatencion)!= 'Sabado'
上使用數字比較datename(weekday,a.fecatencion)!= 'Sabado'
Actos a
表,並用h.codseccion = '18'替換a.codseccion = '18' diagnosticos d
表,因為我沒有看到對它的任何引用 ServiciosMedicos s
表,因為我看不到任何引用 union all
例如:(select * from)表union all(選擇* from),那么至少您將為它們運行一次,而不是兩次 如果必須執行所有這些工作,那么數據庫設計就需要工作。 我堅信數據應該以查詢的形式存儲。考慮在數據插入/更新后添加列以執行此操作,就可以創建計算字段。 這樣就不必每次運行查詢時都發生。
這部分看起來可能是主要問題:
AND NOT EXISTS (
select * from diasfestivos af
where (datename(d,a.fecatencion) + datename(m,a.fecatencion))=
(datename(d,af.fechafestiva) + datename(m,af.fechafestiva))
AND a.fecAtencion +1 > af.fechafestiva
AND a.fecAtencion -1 < af.fechafestiva
and datepart(yy,af.fechafestiva)='1990'
)
看起來基本上是這樣:
AND NOT EXISTS (
SELECT NULL FROM diasfestivos af
WHERE af.fechafestiva BETWEEN '19900101' AND '19910101'
AND DATEPART(d, a.fecatencion) = DATEPART(d, af.fechafestiva)
AND DATEPART(m, a.fecatencion) = DATEPART(m, af.fechafestiva)
AND a.fecatencion != af.fechafestiva
)
我一直在嘗試找到一種方法來處理您的日期相同但又不同的年份,而不必在日期上執行多項功能,但是我沒有設法做到。
也嘗試“ SQL Server事件探查器”。
考慮一下連接的順序,以便首先過濾掉大塊數據。
您應該學習如何使用“ DateDiff”。 該查詢應使用此構造來僅獲取2009年的記錄:
DATEDIFF(yy, a.fecAtencion, '2009-01-01')
其他幾件事...
首先-請勿進行約會。
靜態日期(例如“ 2009-01-01”)具有隱含的午夜(00:00:00)開始時間。 因此,從2009年開始,您根本不需要演員表,因為實際上2009年的所有情況都比“ 2009-01-01”大。 您也可以使用“ 2010-01-01”作為結束日期,因為2009年之前的所有日期(2010年沒有)將在此之前。
不使用這些丑陋轉換的另一個原因是,您可以在SQL查詢中指定小時,分鍾,秒和毫秒,例如:'2009-01-01 00:00:00:000',如果您不想離開在該區域的查詢不明確。
關於使用探查器等的其他建議仍然很好。 但是我敢打賭,您的問題出在您的日期處理上。
以vb.net為例。
我的目標是減輕對sql服務器分組/計數結果的壓力。
嘗試這種額外的優化,看看是否可以減少執行時間?
strsql="
select gd.descripcion
from diagnosticos d,gruposdiagnosticos gd, ServiciosMedicos s, pacientes p,Actos a,historias h
where p.codigo=h.codpaciente and p.codigo=a.codpaciente and p.codigo=h.codpaciente and p.codigo=s.codpaciente and h.codpaciente=a.codpaciente and h.codpaciente=s.codpaciente and a.codpaciente=s.codpaciente and h.numhistoria=a.numhistoria and h.numhistoria=s.numhistoria and a.numacto=s.numacto and h.codseccion=a.codseccion and a.codseccion=s.codseccion and d.codigo=s.codDiagnostico and gd.codigo=d.codgrupo
and p.codcompañia ='35' and a.codseccion ='18'
and (CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >='20090101')
and (CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) <='20091231')
and h.modo ='Urgente'
and datename(weekday,a.fecatencion)!= 'Sabado'
and datename(weekday,a.fecatencion)!= 'Domingo'
AND NOT EXISTS (select * from diasfestivos af where (datename(d,a.fecatencion) + datename(m,a.fecatencion))=(datename(d,af.fechafestiva) + datename(m,af.fechafestiva)) AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >= af.fechafestiva AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) < af.fechafestiva + 1 and datepart(yy,af.fechafestiva)='1990')
AND NOT EXISTS (SELECT * FROM diasfestivos af WHERE CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >= af.fechafestiva AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) < af.fechafestiva + 1 AND datepart(yy,af.fechafestiva)!=1990)
"
cmd = new sqlcommand(strsql, conn)
cmd.commandtimeout = 480
da = new sqldataadapter(cmd)
dt = new datatable
da.fill(dt)
dim dv as new dataview(dt)
dv.sort = "descripcion"
dt2 = dv.totable(true, "descripcion") 'simulate a select distinct from result
dt2.columns.add("total")
for each dr as datarow in dt2.rows
dr("total") = dt.select("descripcion = '" & dr("descripcion ") & "'").length
next
dt2.acceptchanges()
gridview2.datasource = dt2
gridview2.databind
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.