0

假设我有一个包含十亿条记录的表 X。

Table X

ProductID AccountID ContractID

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

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

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

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

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

4

3 回答 3

2

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

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

SELECT ProductID, AccountID, ContractID
FROM X
INNER JOIN #temp t ON t.ProductID = X.ProductID AND t.AccountID = X.AccountID
于 2013-06-12T15:29:13.630 回答
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
...
于 2013-06-12T15:01:31.220 回答
0

我猜你的内存映射在你的 Java 程序中?如果是这样,我认为没有独立于数据库的有效解决方案。我能想到的最好的方法是尝试在内存映射中找到连续的 id 范围,以便您可以编写 SELECT FROM X where ID >= xx AND id <= yy 并避免选择重复的 id。

于 2013-06-12T15:07:15.553 回答