sql – WHERE ID IN(1,2,3,4,5,…)是最有效的?

我知道这个话题已经被打死了,但似乎互联网上的许多文章经常寻找最优雅的方式,而不是最有效的方式来解决它.这是问题.我们正在构建一个应用程序,其中一个常见的数据库查询将涉及到基于用户提供的ID列表的操纵(SELECT和UPDATE).预计这个表有数十万行,用户提供的ID列表可能是无限制的,它们最有可能是数十或数百(我们可能稍后会因性能原因而限制).

如果我对数据库的一般工作方式的理解是正确的,最有效的是简单地使用WHERE ID IN(1,2,3,4,5,…)动态构建和构建查询.问题的核心是ID的输入列表将是真正的任意的,所以无论数据库如何聪明,或者我们如何巧妙地实现它,我们总是有一个随机的整数子集开始,所以最终每个方法都必须无论如何,内部归结为像WHERE ID IN(1,…)的东西.

人们可以在网络上找到许多方法.例如,一个涉及声明一个表变量,将ID的列表作为逗号分隔的字符串传递给一个存储过程,在存储过程中将其分解,将该ID插入到表变量中,并加入它的主表,这个:

-- 1. Temporary table for ID’s:
DECLARE @IDS TABLE (ID int);

-- 2. Split the given string of ID’s,and each ID to @IDS.
-- Omitted for brevity.

-- 3. Join the main table to @ID’s:
SELECT MyTable.ID,MyTable.someColumn
FROM MyTable INNER JOIN @IDS ON MyTable.ID = @IDS.ID;

将字符串操作的问题放在一边,我认为在这种情况下本质上发生的是,在第三步中,sql Server说:“谢谢,这很好,但是我只需要一个ID的列表”,它扫描表变量@IDS,然后n在MyTable中寻找,其中n是ID的编号.我做了一些基本的性能评估,并检查了查询计划,似乎这是会发生的.所以表变量,字符串连接和分割以及所有额外的INSERT都没有.

我对么?还是我缺少什么?真的有一些聪明和更有效的方式吗?基本上,我所说的是,sql Server必须做n索引,无论什么和制定查询,WHERE ID IN(1,…)是最直接的方式去问问.

解决方法

那么这取决于真正的事情.用户如何选择这些ID?

此外,这不仅仅是效率;还有安全性和正确性要担心.用户何时以及如何告诉数据库有关其ID选择?如何将它们合并到查询中?

将选定的ID放入可以加入的单独表格(或使用WHERE EXISTS对照)可能会更好.

我会给你,对于一个小的(用户生成的)n,你不太可能比IN(1,3..n)做得更好.但是,您需要考虑如何生成查询.你要使用动态sql吗?如果是这样,你如何从注射中取得安全?服务器能否缓存执行计划?

另外,使用额外的表往往更容易.假设您正在为电子商务网站构建购物车.而不是担心跟踪购物车客户端或会话,每次用户进行选择时,最好更新ShoppingCart表.这也避免了如何安全地设置查询的参数值的整个问题,因为您一次只进行一次更改.

不要忘记旧格言(道歉Benjamin Franklin):

He who would Trade correctness for performance deserves neither

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...