如何编写有效处理大量记录的查询?

时间:2013-06-12 14:58:14

标签: java sql

假设我的表X有十亿条记录。

Table X

ProductID AccountID ContractID

ProductIDAccountID为表X创建了一个复合键。

现在,在内存中,我有一个包含一百万(ProductID,AccountID)对的地图(比如Java HashMap)。

我想创建一个文件,其中包含所有(ProductID,AccountID)以及该对的相应ContractID。

现在我可以使用for循环,对于每个(ProductID,AccountID),我可以查询表,但是我必须这样做一百万次,这将是非常低效的。

问题是,如何编写有效执行此操作的查询?或者可以写这样的查询?还有另一种出路吗?

3 个答案:

答案 0 :(得分:2)

如果速度和效率很重要,那么在IN子句中有一百万个“联合”或一百万个项目的查询是不可接受的。

更高效的解决方案是将ProductID / AccountID hashmap批量插入到临时表中,我们称之为#temp。我不打算描述批量插入,因为这取决于数据库。然后,您可以执行简单的连接查询:

SELECT ProductID, AccountID, ContractID
FROM X
INNER JOIN #temp t ON t.ProductID = X.ProductID AND t.AccountID = X.AccountID

答案 1 :(得分:1)

在不知道确切的SQL方言的情况下,我会执行INNER JOIN

SELECT ProductID, AccountID, ContractID
FROM X
INNER JOIN MemTable m ON m.ProductID = X.ProductID AND m.AccountID = X.AccountID

您现在添加了Java作为标记,所以我认为地图在您的Java应用程序中是正确的吗?如果是这样,它会变得很难 - 你实际上可能需要查询数百万次。

另一方面,您可以构造一个包含一个单独的大型SQL语句的字符串,如下所示:

SELECT * FROM X WHERE ProductID IN (...) AND AccountID IN (...)

您的循环只会填写以逗号分隔的产品ID和帐户ID列表。然后你发出一次该命令。例如,该命令应如下所示,假设两个ID都是数字:

SELECT * FROM X WHERE ProductID IN (1,2,3,4) AND AccountID IN (99,88,77)

修改
请注意,我的上一个建议可能存在以下缺陷(您必须确定这对您来说是否真的有问题):

假设您的地图包含(1,99)和(3,77),但在表X中还有其他记录(1,77)和(3,99)。我的查询结果将是(1,99),(3,77),(1,77)和(3,99),因为这两个ID都不被视为“实体”,而是单独的。

因此,只要存在包含给定ProductID和AccountID的任意组合的行,就会返回它们。

假设您正在使用的数据库系统允许这样做,您可以将SELECT语句扩展为以下内容:

SELECT ProductID, AccountID, ContractID FROM X WHERE ProductID = <ValueFromMap> AND AccountID = <ValueFromMap>
UNION ALL
SELECT ProductID, AccountID, ContractID FROM X WHERE ...
UNION ALL
...

答案 2 :(得分:0)

我猜你的内存映射在你的Java程序中?如果是这样,我认为没有与数据库无关的有效解决方案。我能想到的最好的方法是尝试在你的内存映射中找到连续的id范围,这样你就可以编写SELECT FROM X,其中ID&gt; = xx AND id&lt; = yy并避免选择重复的id。