我有一些用c#,mvc和mssql编写的web应用程序
用户可以通过某种形式选择一些产品
表格中有两个网格。一个网格显示用户可以选择用于将来处理的产品。其他网格显示已选择的产品。
这样的工作是这样的:
1.用户通过复选框选择第一个网格中的产品
然后他点击“添加”按钮
在此之后,网格会被刷新。第二个网格显示添加的产品,第一个网格显示所有没有第二个网格产品的产品。
目前,数据库中有大约50.000种产品。
当用户选择要添加的产品太多时,问题在于网格刷新。
用于frist网格的Sql看起来像:
SELECT ProductId, Name, Description, {other columns}
FROM Products
WHERE ProductId NOT IN ({ list of selected ProductId to add })
如果{要添加的所选ProductId列表}有多个元素(即10.000),则sql语句执行时间过长,甚至超时。
我对此感到困惑,并且不知道如何解决这个问题。 任何帮助将不胜感激
答案 0 :(得分:1)
您可以将产品过滤器存储在另一个表中。此表可能是临时的,或者,如果您想记住选择,可以将其编入永久表中。
所以你的陈述看起来像是
SELECT
ProductId
, Name
, Description
...
FROM
Products
WHERE
ProductId NOT IN
(
SELECT Id FROM #ProductFilter
)
,或者
SELECT
ProductId
, Name
, Description
...
FROM
Products
WHERE
ProductId NOT IN
(
SELECT
ProductId
FROM
ProductFilter
WHERE
FilterId = @filterId
)
如何创建临时表的方法,或者过滤器如何插入ProductFilter
的方法将根据过滤器传递给查询的方式而有所不同。
如果您使用的是SQL Server 2008+,则可以使用table valued parameter。那么查询显然会是这样的。
SELECT
ProductId
, Name
, Description
...
FROM
Products
WHERE
ProductId NOT IN
(
SELECT Id FROM @ProductFilter
)
如果你的问题是关于性能调优,那么,我需要更多关于你的Schema的信息,这是一个有代表性的数据库实例,还有一些时间来调整和测试一些想法。
然而,通过像这样的大规模排除过滤器的想法似乎是错误的,我无法相信用户是手动逐个排除这些产品。即使是这种情况,我认为,包含过滤器会导致使用内部联接更简单的查询。
答案 1 :(得分:1)
如果我理解正确,主要问题似乎是您没有在数据库中的任何位置存储所选产品的列表。如果你是,你可以执行这样的查询。
select product_id
from products
where product_id not in (select product_id from customer_selected_products);
现在,这不会像许多查询一样好,因为你将从产品中返回数万行。 (您将返回尚未选择的所有产品ID号。)但它在此处以合理的速度执行(在customer_selected_products中为21行,10,000行。)
答案 2 :(得分:0)
您声明用户可以按名称或该名称的一部分过滤掉产品。有你的锚。用户不太可能排除10 000个不同的产品名称,但更有可能排除10 000个具有特定属性的产品(例如名称中的品牌)。
您可以使用更一般的标准,而不是发送产品ID的背面和堡垒。这将导致如下查询:
select *
from products
where p.name NOT LIKE 'brand1%'
and p.name NOT LIKE 'specific product'
请注意,为了获得更好的性能,将这些标准存储在第二个表中是明智的。现在,您可以构建一个类似的查询:
select p.*
from products p
join criteria c
on p.name NOT LIKE c.name
答案 3 :(得分:0)
我建议你将TVP(表值参数)发送回服务器。之后,您的查询可以像:
SELECT p.ProductId, Name, Description, {other columns}
FROM Products p
left join @ExceptedProducts ep on p.ProductId=ep.ProductId
WHERE where ep.ProductId is null
这应该是最快速,最干净的方式。
答案 4 :(得分:0)
感谢您的意见和建议。
我目前的解决方案是从db获取所有产品(如果需要,过滤)并直接在c#代码中排除选定的产品(不在sql语句中)。
我做了一些测试,它在我的场景中工作得很好。 即我可以在2秒内及时向第二个网格添加100.000个产品。 我也考虑缓存sql结果。它可以提供更好的性能。
如果你知道这个解决方案的任何缺点,请现在就让我。