1. 程式人生 > >資料庫查詢優化(使用union 和 union all 的區別)

資料庫查詢優化(使用union 和 union all 的區別)

在專案中遇到一個問題,建立一個檢視,主要內容是:
SELECT   info.InfoCode, info.YearOfData, info.MonthOfData, info.ProjectPropertyID, property.PropertyName, info.ProjectCode,
                info.ProjectName, info.ProjectApprovedBudget, progress.ProjectImageProgress, contracts.ContractCode,
                contracts.ContractName, contracts.ContractAccount, upload.UploadEmployeeName AS Uploader,
                upload.UploadEmployeeNumber AS UploaderNum, upload.UploadDateTime as UploadDateTime
FROM      ProjectSummaryInfo info LEFT JOIN
                ProjectContract contracts ON info.InfoCode = contracts.InfoCode LEFT JOIN
                ProjectProgress progress ON info.InfoCode = progress.InfoCode JOIN
                ProjectProperty property ON info.ProjectPropertyID = property.ID JOIN
                ProjectUploadedFile upload ON info.ProjectUploadedFileID = upload.ID
UNION
SELECT   info.InfoCode, info.YearOfData, info.MonthOfData, info.ProjectPropertyID, property.PropertyName, info.ProjectCode,
                info.ProjectName, info.ProjectApprovedBudget, progress.ProjectImageProgress, contracts.ContractCode,
                contracts.ContractName, contracts.ContractAccount, upload.UploadEmployeeName AS Uploader,
                upload.UploadEmployeeNumber AS UploadNum, upload.UploadDateTime as UploadDateTime
FROM      ProjectTechImprove info LEFT JOIN
                ProjectTechImproveContract contracts ON info.InfoCode = contracts.InfoCode LEFT JOIN
                ProjectTechImproveProgress progress ON info.InfoCode = progress.InfoCode JOIN
                ProjectProperty property ON info.ProjectPropertyID = property.ID JOIN
                ProjectUploadedFile upload ON info.ProjectUploadedFileID = upload.ID

單個執行都是很快的,加在一起都不需要一秒鐘,但是union 之後查詢出來需要10s中左右,結果也僅僅就是59171條記錄,但是為什麼這麼慢呢?

後來查詢資料才知道union會自動壓縮多個結果集合中的重複結果,如果換做union all則會將所有的結果全部顯示出來,不管是不是重複,這樣就會快很多,

於是我將union 替換為union all

SELECT   info.InfoCode, info.YearOfData, info.MonthOfData, info.ProjectPropertyID, property.PropertyName, info.ProjectCode,
                info.ProjectName, info.ProjectApprovedBudget, progress.ProjectImageProgress, contracts.ContractCode,
                contracts.ContractName, contracts.ContractAccount, upload.UploadEmployeeName AS Uploader,
                upload.UploadEmployeeNumber AS UploaderNum, upload.UploadDateTime as UploadDateTime
FROM      ProjectSummaryInfo info LEFT JOIN
                ProjectContract contracts ON info.InfoCode = contracts.InfoCode LEFT JOIN
                ProjectProgress progress ON info.InfoCode = progress.InfoCode JOIN
                ProjectProperty property ON info.ProjectPropertyID = property.ID JOIN
                ProjectUploadedFile upload ON info.ProjectUploadedFileID = upload.ID
UNION ALL
SELECT   info.InfoCode, info.YearOfData, info.MonthOfData, info.ProjectPropertyID, property.PropertyName, info.ProjectCode,
                info.ProjectName, info.ProjectApprovedBudget, progress.ProjectImageProgress, contracts.ContractCode,
                contracts.ContractName, contracts.ContractAccount, upload.UploadEmployeeName AS Uploader,
                upload.UploadEmployeeNumber AS UploadNum, upload.UploadDateTime as UploadDateTime
FROM      ProjectTechImprove info LEFT JOIN
                ProjectTechImproveContract contracts ON info.InfoCode = contracts.InfoCode LEFT JOIN
                ProjectTechImproveProgress progress ON info.InfoCode = progress.InfoCode JOIN
                ProjectProperty property ON info.ProjectPropertyID = property.ID JOIN
                ProjectUploadedFile upload ON info.ProjectUploadedFileID = upload.ID

這次查詢只要了3.5秒,慶幸的是專案沒有要求去重,而且本次查詢union 兩邊的資料是沒有重複的,使用union all效率高了很多。

但是如果要求去掉重複的話,union all 就不適合了。

後來我又蒐集了一下,萬一碰上要求去重,而且兩邊有交叉重複的怎麼辦?

其實這時我們可以先order 之後再查詢,這樣會省去很多交叉比對去重過程的時間,或者使用臨時表加入查詢條件之後再union也是個不錯的選擇

總結一下  關於查詢語句中的交集並集差集中不同方法的區別:

Union:對兩個結果集進行並集操作,不包括重複行,同時進行預設規則的排序;

Union All:對兩個結果集進行並集操作,包括重複行,不進行排序;

Intersect:對兩個結果集進行交集操作,不包括重複行,同時進行預設規則的排序;

Minus:對兩個結果集進行差操作,不包括重複行,同時進行預設規則的排序。