[英]SQL Server - Create Index on query over multiple tables?
我在優化特定的SQL查詢時遇到了大問題。 它包含多個內部聯接,並且向每個表添加索引根本不會提高性能。
我的查詢:
declare @categoryid int = 2;
SELECT [Scanresultebay].Id
, [Scanresultebay].Productebayid
, [Scanresultebay].Price
, [Scanresultebay].Stockamount
, [Scanresultebay].Timestamp
, [Category].Categoryname
, (
SELECT TOP 1 [Scanresultebay].price
FROM [Scanresultebay]
INNER JOIN [Productebay] ON [Productebay].id = .[Scanresultebay].productebayid
INNER JOIN [EbaySeller] on [EbaySeller].id = [ProductEbay].ebaysellerid
WHERE [dbo].[EbaySeller].id = 28
and [ProductEbay].categoryid = @categoryid
ORDER BY [Scanresultebay].Id DESC
) AS 'OurPrice'
FROM [Scanresultebay]
INNER JOIN [Productebay] ON [Productebay].Id = [Scanresultebay].productebayid
INNER JOIN [Category] ON [Category].Id = [Productebay].categoryid
WHERE [Scanresultebay].productebayid in (
SELECT [Scanresultebay].productebayid
FROM [Scanresultebay]
INNER JOIN [ProductEbay] ON [ProductEbay].id = [ScanResultEbay].ProductEbayId
INNER JOIN [Category] ON [Category].Id = ProductEbay.CategoryID
WHERE [ProductEbay].categoryid = @categoryid and [ProductEbay].expired is null
GROUP BY [Scanresultebay].ProductEbayId
)
and [Scanresultebay].Id in (
SELECT max(Id)
FROM [Scanresultebay]
WHERE productebayid = [Scanresultebay].ProductEbayId
and [Scanresultebay].Price <> 0
GROUP BY [Scanresultebay].[ProductEbayId]
);
我的索引(如SQL Server所建議的那樣):
CREATE NONCLUSTERED INDEX [ind_GetPrice]
ON [dbo].[ScanResultEbay] ([Id],[ProductEbayId]) include ([Stockamount], [Timestamp], [Price])
我需要此查詢以在我的網站的儀表板上顯示信息。 因此,我必須使用此查詢遍歷每個類別(總計100個)。 這持續長達30-40秒,這當然是太多了。
創建視圖是一個問題,因為我還必須為子查詢聲明categoryid的參數,並且無法將參數傳遞給視圖。
所以我的問題是:
這不是一個完整的答案 ,而是有關現有語法的注釋中您的問題的答案。
代替:
WHERE [Scanresultebay].productebayid in (
SELECT [Scanresultebay].productebayid
FROM [Scanresultebay]
INNER JOIN [ProductEbay] ON [ProductEbay].id = [ScanResultEbay].ProductEbayId
INNER JOIN [Category] ON [Category].Id = ProductEbay.CategoryID
WHERE [ProductEbay].categoryid = @categoryid and [ProductEbay].expired is null
GROUP BY [Scanresultebay].ProductEbayId
)
用這個:
WHERE EXISTS (
SELECT 1
FROM [Scanresultebay] t1
INNER JOIN [ProductEbay] ON [ProductEbay].id = t1.ProductEbayId
INNER JOIN [Category] ON [Category].Id = ProductEbay.CategoryID
WHERE [ProductEbay].categoryid = @categoryid
AND [ProductEbay].expired is null
AND [Scanresultebay].productebayid = t1.productebayid
)
請注意,我已經將[Scanresultebay].productebayid
從主查詢的where子句移到內部查詢的where子句中。 Exists
將計算為true
括號返回結果中查詢,否則false
。
另外,最后一個in
運算符應替換為=
,因為select SELECT max(Id)
將僅返回單個值。
我將嘗試將此查詢重寫為類似的內容(這僅是使用CTE的概念證明):
declare @categoryid int = 2;
with products_a as (
select [scanresultebay].productebayid
from [scanresultebay]
inner join [productebay] on [productebay].id = [scanresultebay].productebayid
inner join [category] on [category].id = productebay.categoryid
where [productebay].categoryid = @categoryid and [productebay].expired is null
group by [scanresultebay].productebayid
), -- 1st from where clause
products_b as (
select max(id) id
from [scanresultebay]
where productebayid = [scanresultebay].productebayid
and [scanresultebay].price <> 0
group by [scanresultebay].[productebayid]
), -- 2nd from where clause
items as (
select [scanresultebay].id
, [scanresultebay].productebayid
, [scanresultebay].price
, [scanresultebay].stockamount
, [scanresultebay].timestamp
, [category].categoryname
from [scanresultebay]
inner join [productebay] on [productebay].id = [scanresultebay].productebayid
inner join [category] on [category].id = [productebay].categoryid
)
select
items.*
from
items
join
products_a
on
products_a.productebayid = items.productebayid
join
products_b
on
products_b.id = items.id
;
它消除了IN
並且通過拆分查詢,可以更輕松地檢查/優化部分查詢。
我無法運行它,所以可能會有小錯誤。
它不包含有關價格的部分-我沒有抓住您使用的聯接,但是我會使用類似的東西(作為上面查詢的一部分):
select id,
[scanresultebay].productebayid,
price,
row_number() over (partition by [scanresultebay].productebayid order by [scanresultebay].id desc) nr -- top price is nr = 1 per each [scanresultebay].productebayid
from [scanresultebay]
inner join [productebay] on [productebay].id = .[scanresultebay].productebayid
inner join [ebayseller] on [ebayseller].id = [productebay].ebaysellerid
where [dbo].[ebayseller].id = 28
and [productebay].categoryid = @categoryid
我假設[scanresultebay].productebayid
是加入的關鍵。 上面的查詢(調整后)可以添加到上面的第一個查詢中,並加入最終查詢中。
我缺少用於格式和語法檢查的好工具,因此請原諒上面的任何錯誤。
您應該為每個外鍵創建索引。
如果where子句包含單個表的多個字段,則還應該在這些組合上創建索引。
編輯:
詳細說明:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.