Postgresql - 超过 3000 个值的 IN 子句优化
Posted
技术标签:
【中文标题】Postgresql - 超过 3000 个值的 IN 子句优化【英文标题】:Postgresql - IN clause optimization for more than 3000 values 【发布时间】:2021-02-23 09:36:12 【问题描述】:我有一个应用程序,用户将上传一个包含超过 10,000 行的 excel 文件(.xlsx 或 .csv),其中包含要在数据库中查找的值的单列“partId”
我将读取 excel 值并将其存储在列表对象中,并将列表作为参数传递给 Spring Boot JPA 存储库 find 方法,该方法在内部构建 IN 子句查询:
// Read excel file
stream = new ByteArrayInputStream(file.getBytes());
wb = WorkbookFactory.create(stream);
org.apache.poi.ss.usermodel.Sheet sheet = wb.getSheetAt(wb.getActiveSheetIndex());
Iterator<Row> rowIterator = sheet.rowIterator();
while(rowIterator.hasNext())
Row row = rowIterator.next();
Cell cell = row.getCell(0);
System.out.println(cell.getStringCellValue());
vinList.add(cell.getStringCellValue());
//JPA repository method that I used
findByPartIdInAndSecondaryId(List<String> partIds);
我阅读了很多文章并在上述情况下遇到了相同的情况,即使用 IN 查询对于庞大的数据列表是低效的。
如何优化上述场景或编写新的优化查询?
另外,请告诉我是否有比上述代码sn-p更优化的读取excel文件的方式
这会很有帮助!!提前致谢!
【问题讨论】:
在 *** 上有一些使用VALUES
连接而不是 in
的示例。你试过这个吗?
@madflow,我试过了。我想知道是否有任何其他优化的方式来处理大量的值
@LaurenzAlbe,由于我将通过 API 从用户界面接收列表,因此我必须在应用程序和数据库之间移动大型列表。我不知道如何有效地通过列表
@LaurenzAlbe,恐怕我不清楚你的陈述:(。你能分享任何示例查询吗?
【参考方案1】:
如果列表真的很大,你永远不会像闪电一样快。
我看到了几个选项:
正如您在问题中提到的那样,发送带有大量 IN
列表的查询。
构造一个带有大 VALUES
子句的连接语句:
SELECT ... FROM mytable
JOIN (VALUES (42), (101), (43), ...) AS tmp(col)
ON mytable.id = tmp.col;
使用这些值创建一个临时表并与之连接:
BEGIN;
CREATE TEMP TABLE tmp(col bigint) ON COMMIT DROP;
然后
COPY tmp FROM STDIN; -- if Spring supports COPY
或
INSERT INTO tmp VALUES (42), (101), (43), ...; -- if not
然后
ANALYZE tmp; -- for good statistics
SELECT ... FROM mytable
JOIN tmp ON mytable.id = tmp.col;
COMMIT; -- drops the temporary table
哪一个最快最好根据您的案例反复试验来确定;我不认为可以说其中一种方法总是胜过其他方法。
一些注意事项:
解决方案 1. 和 2. 可能会产生非常大的语句,而解决方案 3. 可以分成更小的块。
解决方案 3. 很可能会更慢,除非列表真的很大。
【讨论】:
非常感谢!我会尝试所有这些方法并更新每个解决方案的状态。以上是关于Postgresql - 超过 3000 个值的 IN 子句优化的主要内容,如果未能解决你的问题,请参考以下文章