我在优化特定的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的参数,并且参数不能传递给视图。
所以我的问题:
答案 0 :(得分:2)
我会尝试将此查询重写为类似的内容(这只是使用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
是加入的关键。
上面的查询(调整后)可以添加到上面的第一个查询并加入
在最后的查询中。
我缺乏格式和语法检查的好工具,所以请原谅上面的任何错误。
答案 1 :(得分:0)
您应该为每个外键创建索引。
如果你的where子句包含单个表的多个字段,那么你也应该在这些组合上创建索引。
编辑:
详细说明: