我需要编写一个查询来检索一个大的id列表。

我们确实支持许多后端(MySQL, Firebird, SQLServer, Oracle, PostgreSQL…),所以我需要写一个标准的SQL。

id集的大小可能很大,查询将以编程方式生成。那么,最好的方法是什么呢?

1)使用IN编写查询

SELECT * FROM TABLE WHERE ID IN (id1, id2, ..., idn)

我的问题是。如果n很大会怎样?还有,性能如何?

2)使用OR编写查询

SELECT * FROM TABLE WHERE ID = id1 OR ID = id2 OR ... OR ID = idn

我认为这种方法没有n的限制,但是如果n很大,性能会怎样呢?

3)编写程序解决方案:

  foreach (var id in myIdList)
  {
      var item = GetItemByQuery("SELECT * FROM TABLE WHERE ID = " + id);
      myObjectList.Add(item);
  }

当通过网络查询数据库服务器时,我们使用这种方法遇到了一些问题。通常情况下,做一个查询来检索所有结果比做很多小查询更好。也许我错了。

这个问题的正确解决方法是什么?


当前回答

我想你说的是SqlServer,但在Oracle上你有一个硬限制,你可以指定多少个IN元素:1000。

其他回答

Ed guinness的建议确实是一个性能助推器,我有一个这样的问题

select * from table where id in (id1,id2.........long list)

我做了什么:

DECLARE @temp table(
            ID  int
            )
insert into @temp 
select * from dbo.fnSplitter('#idlist#')

然后inner将temp与主表连接起来:

select * from table inner join temp on temp.id = table.id

性能得到了极大的提高。

示例3将是所有示例中表现最差的,因为您在没有明显原因的情况下无数次地访问数据库。

将数据加载到临时表中,然后进行连接,这将是目前为止最快的方法。之后,IN的工作速度应该比or组略快。

我想你说的是SqlServer,但在Oracle上你有一个硬限制,你可以指定多少个IN元素:1000。

试试这个

SELECT Position_ID , Position_Name
FROM 
position
WHERE Position_ID IN (6 ,7 ,8)
ORDER BY Position_Name

第一个选择绝对是最好的选择。

SELECT * FROM TABLE WHERE ID IN (id1, id2, ..., idn)

然而,考虑到id的列表非常庞大,比如数百万,你应该考虑如下所示的块大小:

将id列表划分为固定数量的块,比如100 块大小应该根据服务器的内存大小来决定 假设你有10000个id,你将有10000/100 = 100个块 每次处理一个数据块,导致100次数据库select调用

为什么要分成几部分?

您将永远不会得到内存溢出异常,这在您的场景中非常常见。 您将优化数据库调用的数量,从而获得更好的性能。

这对我来说一直很有魅力。希望它也能适用于我的其他开发人员:)