SQL 耗时优化
?? 簡介
在平常的開發(fā)中,我們經(jīng)常會編寫各種各樣的 SQL 語句,比如:SQL 查詢、存儲過程、或者視圖查詢等。當我們編寫的 SQL 語句比較復雜,或者表的數(shù)據(jù)量比較大,導致查詢超時!這時,就要去分析我們的 SQL 語句,導致耗時較長的原因,從而優(yōu)化我們的 SQL 語句。
說明:本文僅為筆者所思、所想、所寫,有用之處歡迎借鑒,不對之處歡迎指出。
?
1.?? 內(nèi)連接查詢中,子查詢(關聯(lián)相同的兩張表)使用 TOP 子句解決耗時
1)?? LINQ 語句
var datas = (from t1 in DataContext.Orders
??????????????? join t3 in DataContext.UserInfoes on t1.UserId equals t3.id
??????????????? join t5 in DataContext.Customers on t3.CustomerId equals t5.Id
??????????????? join t7 in (from t1 in DataContext.CateringCategorys
??????????????????????????? join t3 in DataContext.CateringCategorys on t1.CategoryId equals t3.ParentId
??????????????????????????? where t1.Level == 1
??????????????????????????? select new
??????????????????????????? {
??????????????????????????????? CategoryId1 = t1.CategoryId,
??????????????????????????????? CategoryId2 = t3.CategoryId
??????????????????????????? }) on t5.TradeType equals t7.CategoryId2
??????????????? where 1 == 1
??????????????? && (cityId == 0 || t1.CityId == strCityId)
??????????????? && t1.OrderStatusId >= (int)OrderStates.Undelivered && t1.OrderStatusId < (int)OrderStates.Cancelled
??????????????? && t1.PayStatusId != (int)OrderPayStates.Unpaid
??????????????? && (t1.PayTime >= startDate && t1.PayTime < endDate)
??????????????? select new
??????????????? {
??????????????????? CategoryId = t7.CategoryId1,
??????????????????? OrderId = t1.Id,
??????????????????? t1.RealTotal,
??????????????????? t3.CustomerId
??????????????? }).ToArray();
?
2)?? 生成 SQL(sp_executesql 轉換后的同等 SQL 語句)
SELECT
??? [Filter2].[CategoryId1] AS [CategoryId],
??? [Filter1].[Id1] AS [Id],
??? [Filter1].[RealTotal] AS [RealTotal],
??? [Filter1].[CustomerId] AS [CustomerId]
??? FROM?? (SELECT [Extent1].[Id] AS [Id1], [Extent1].[RealTotal] AS [RealTotal], [Extent1].[PayTime] AS [PayTime], [Extent1].[CityId] AS [CityId1], [Extent2].[CustomerId] AS [CustomerId], [Extent3].[TradeType] AS [TradeType]
??????? FROM?? [dbo].[Orders] AS [Extent1]
??????? INNER JOIN [dbo].[UserInfo] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[id]
??????? INNER JOIN [dbo].[Customer] AS [Extent3] ON [Extent2].[CustomerId] = [Extent3].[Id]
??????? WHERE ([Extent1].[OrderStatusId] >= 2) AND ([Extent1].[OrderStatusId] < 10) AND (cast(1 as bigint) <> [Extent1].[PayStatusId]) ) AS [Filter1]
??? INNER JOIN? (SELECT [Extent4].[CategoryId] AS [CategoryId1], [Extent5].[CategoryId] AS [CategoryId2]
??????? FROM? [dbo].[Crm_CateringCategory] AS [Extent4]
??????? INNER JOIN [dbo].[Crm_CateringCategory] AS [Extent5] ON [Extent4].[CategoryId] = [Extent5].[ParentId]
??????? WHERE 1 = [Extent4].[Level] ) AS [Filter2] ON [Filter1].[TradeType] = [Filter2].[CategoryId2]
WHERE ((0 = 0) OR ([Filter1].[CityId1] = '0') OR (([Filter1].[CityId1] IS NULL) AND ('0' IS NULL))) AND ([Filter1].[PayTime] >= '2018-12-01 00:00:00') AND ([Filter1].[PayTime] < '2019-01-01 00:00:00')
?
3)?? 執(zhí)行結果
執(zhí)行以上語句,耗時為:00:01:43.853
?
4)?? SQL 分析
1.?? 首先,我們創(chuàng)建了一個子查詢([Filter1]),關聯(lián)了三張表:Orders、UserInofo 和 Customer,這沒什么好說的,是一個正常查詢。
2.?? 另外,又關聯(lián)了一個子查詢([Filter2]),Crm_CateringCategory 與 Crm_CateringCategory 關聯(lián)(使用 CategoryId 和 ParentId 關聯(lián)),就是因為這個子查詢,導致了較長的耗時!這是為什么呢,這里先打個問號?
3.?? 然后,筆者開始各種猜測
1)?? 這個子查詢數(shù)量量大?NO,只有23記錄。
2)?? 在關聯(lián)的第二個 Crm_CateringCategory 表上再派生一層,再關聯(lián)外層 Crm_CateringCategory 表,并只輸出所需字段?結果還是不行!
3)?? 因為關聯(lián)的是相同的表?對的,就是這個原因!因為,嘗試創(chuàng)建與 CateringCategory 相同的另一張表 CateringCategory_1 去關聯(lián)查詢,耗時問題就解決了。
4)?? 為什么呢,表上加 (NOLOCK) 關鍵字也不管用,原因不祥(如有博友們知道,歡迎指出)!
4.?? 然后,筆者又嘗試在這個子查詢上加上 TOP 子句,結果執(zhí)行耗時變?yōu)榱?00:00:00.740,耗時問題同樣解決了。因為開發(fā)中,不可能再去創(chuàng)建一張相同的一張表。(Linq 只需加上 Take() 方法即可)。
轉載于:https://www.cnblogs.com/abeam/p/10064847.html
總結
- 上一篇: Android app:transfor
- 下一篇: MySQL升级后 MySQL 5.7 时