【发布时间】:2018-05-05 15:09:49
【问题描述】:
我有一个简单的查询
@Query(value = "select * from some_table where consumer_id=:consumerId and store_id=:storeId and cancelled_at is null", nativeQuery = true)
fun checkIfNewConsumer(consumerId: BigInteger, storeId: BigInteger): List<SomeClass?>
当我直接对超过 3000 万行的表运行带有解释的查询时
Index Scan using select_index on some_table (cost=0.56..8.59 rows=1 width=86) (actual time=0.015..0.015 rows=0 loops=1)
Index Cond: ((consumer_id = 1234) AND (store_id = 4) AND (cancelled_at IS NULL))
Planning time: 0.130 ms
Execution time: 0.042 ms
当我使用 Spring Boot 通过请求运行相同的查询时:
{"Plan"=>{"Total Cost"=>1317517.92, "Relation Name"=>"some_table", "Parallel Aware"=>"?", "Filter"=>"?", "Alias"=>"some_table", "Node Type"=>"Seq Scan", "Plan Width"=>86, "Startup Cost"=>0.0, "Plan Rows"=>912}}
Execution time: 9613 ms
上面的春季启动计划来自新的遗物。 如您所见,它默认为每个查询使用 Seq scan,而不是 Index scan。我已经真空分析假设它是数据库(没有骰子),我尝试了查询的变体,没有骰子。它在plsql中总是看起来很完美,通过spring borks。
我们将不胜感激任何建议。
编辑 2:潜在解决方案
我们发现,通过禁用准备好的语句,将 ?preferQueryMode=simple 添加到您的连接 URL:jdbc:postgresql://localhost:5432/postgres?preferQueryMode=simple 得到了使用索引扫描的查询。
我们需要了解如何?为什么?为什么是现在?
编辑 1:技术栈
- 弹簧靴2.0M5
- 科特林
- PostgreSQL 9.6.2
编辑:解决方案@Vlad Mihalcea
请不要使用 preferQueryMode=simple,除非您完全确定它的含义。显然,https://gist.github.com/vlsi/df08cbef370b2e86a5c1 中描述了您的问题。我猜你在数据库中有 BigInt,在 Kotlin 代码中有 BigInteger。你可以在 Kotlin 中使用 Long 吗?
–弗拉基米尔·希特尼科夫
【问题讨论】:
-
请不要使用
preferQueryMode=simple,除非您完全确定它的含义。显然,gist.github.com/vlsi/df08cbef370b2e86a5c1 中描述了您的问题。我猜你在数据库中有bigint,在Kotlin 代码中有BigInteger。你可以在 Kotlin 中使用Long吗? -
您能否将其发布为答案以便我接受?这确实是解决方案
标签: sql postgresql hibernate spring-boot spring-data-jpa