我需要编写一个查询来检索一个大的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);
  }

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

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


当前回答

在一个有5亿条记录的Azure SQL表上执行SELECT * FROM MyTable where id in()命令导致等待时间为> 7min!

这样做会立即返回结果:

select b.id, a.* from MyTable a
join (values (250000), (2500001), (2600000)) as b(id)
ON a.id = b.id

使用连接。

其他回答

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

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

试试这个

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

第一种选择 在临时表中添加id,并添加与主表的内部连接。

CREATE TABLE #temp (column int)
INSERT INTO #temp (column) 
SELECT t.column1 FROM (VALUES (1),(2),(3),...(10000)) AS t(column1)

在一个有5亿条记录的Azure SQL表上执行SELECT * FROM MyTable where id in()命令导致等待时间为> 7min!

这样做会立即返回结果:

select b.id, a.* from MyTable a
join (values (250000), (2500001), (2600000)) as b(id)
ON a.id = b.id

使用连接。

选项1是唯一好的解决方案。

Why?

Option 2 does the same but you repeat the column name lots of times; additionally the SQL engine doesn't immediately know that you want to check if the value is one of the values in a fixed list. However, a good SQL engine could optimize it to have equal performance like with IN. There's still the readability issue though... Option 3 is simply horrible performance-wise. It sends a query every loop and hammers the database with small queries. It also prevents it from using any optimizations for "value is one of those in a given list"