这是我的问题:我在数据库中有一组表,其中填充了来自包含产品信息的客户端的数据。除了基本的产品信息,还有关于制造商的信息,以及这些产品的类别(一个产品可以是一个或多个类别)。这些类别然后被称为“产品类别”,这些产品在哪些商店可用。这些表每周根据客户的提要更新一次。
由于出于我们的目的,某些产品类别与我们的目的相同或密切相关,因此还有另一种级别的类别称为“一般类别”,一般类别可以包含一个或多个产品类别。
对于这些表的范围,这里有一些粗略的数字:
Data Tables:
Products: 475,000
Manufacturers: 1300
Stores: 150
General Categories: 245
Product Categories: 500
Mapping Tables:
Product Category -> Product: 655,000
Stores -> Products: 50,000,000
Run Code Online (Sandbox Code Playgroud)
现在,对于实际问题:作为我们软件的一部分,我们需要选择n
随机产品,给定商店和一般类别。但是,我们还需要确保制造商的良好组合,因为在某些类别中,单个制造商主导了结果,随机选择行会导致结果强烈偏向该制造商。
当前采用的解决方案适用于大多数情况,包括选择与商店和类别标准匹配的所有行,按制造商对它们进行分区,并在其分区中包含它们的行号,然后从中选择行号为该制造商小于n
,并用于ROWCOUNT
钳制返回到 的总行数n
。
这个查询看起来像这样:
SET ROWCOUNT 6
select p.Id, GeneralCategory_Id, Product_Id, ISNULL(m.DisplayName, m.Name) AS Vendor,
MSRP, MemberPrice, FamilyImageName
from (select p.Id, gc.Id GeneralCategory_Id,
p.Id Product_Id, ctp.Store_id, Manufacturer_id,
ROW_NUMBER() OVER (PARTITION BY Manufacturer_id ORDER BY NEWID()) AS 'VendorOrder',
MSRP, MemberPrice, FamilyImageName
from GeneralCategory gc
inner join GeneralCategoriesToProductCategories gctpc ON gc.Id=gctpc.GeneralCategory_Id
inner join ProductCategoryToProduct pctp on gctpc.ProductCategory_Id = pctp.ProductCategory_Id
inner join Product p on p.Id = pctp.Product_Id
inner join StoreToProduct ctp on p.Id = ctp.Product_id
where gc.Id = @GeneralCategory and ctp.Store_id=@StoreId and p.Active=1 and p.MemberPrice >0) p
inner join Manufacturer m on m.Id = p.Manufacturer_id
where VendorOrder <=6
order by NEWID()
SET ROWCOUNT 0
Run Code Online (Sandbox Code Playgroud)
(我试图对其进行某种格式化以使其更干净,但我认为这并没有真正的帮助)
使用执行计划运行此查询表明,对于这些表中的大多数,它正在执行聚集索引查找。有两个操作占用了大约 90% 的时间:
在没有很多产品的类别上,性能是可以接受的(<50ms),但是较大的类别可能需要几百毫秒,最大的类别需要 3 秒(大约有 17 万个产品)。
从这一点来看,我似乎有两种方法:
有没有人对这些项目中的任何一个有任何意见?
小智 1
计划 C:对于每个商店和一般类别,使用您当前的方法随机选择 N 个产品,并将其临时存储在某个地方。每次有人获取您预取的随机组之一时,请重新填充该商店/类别。如果不需要是最新的,那么就不需要让客户端等待您获取最新数据。
归档时间: |
|
查看次数: |
1462 次 |
最近记录: |