Java QueryDsl distinct查询太慢

Java QueryDsl distinct查询太慢,java,database,oracle,jpa,querydsl,Java,Database,Oracle,Jpa,Querydsl,我正在使用Java中的QueryDsl和Oracle数据库 我的查询如下所示(实名改为虚名,但查询完全相同): QTableA qTabA=QTableA.tableA; QTableB qTabB=QTableA.tableB; QTableC qTabC=QTableA.tableC; 列表结果=查询工厂 .select(Projections.constructor(ResultClass.class、qTabA.col1、qTabB.col1、qTabC.col1、qTabC.col2)

我正在使用Java中的QueryDsl和Oracle数据库

我的查询如下所示(实名改为虚名,但查询完全相同):

QTableA qTabA=QTableA.tableA;
QTableB qTabB=QTableA.tableB;
QTableC qTabC=QTableA.tableC;
列表结果=查询工厂
.select(Projections.constructor(ResultClass.class、qTabA.col1、qTabB.col1、qTabC.col1、qTabC.col2))
.来自(qTabA、qTabB、qTabC)
.式中(qTabA.col2.eq(123))
其中(qTabA.col3.eq(“测试”))
.where(qTabA.col4.eq(qTabB.col2))
.式中(qTabA.col4.eq(qTabC.col2))
.distinct()
.抵销(抵销)
.限额
.fetch();
该查询将获取大约150万行,这就是我使用
offset()
limit()
的原因

我不能使用
.iterator()
,因为如果您想在迭代器尚未关闭的情况下提交事务,则会失败

因为我添加了distinct,所以我的查询速度非常慢→ 不能用的慢

但是,我不能在Java代码中执行distinct检查,因为我不能一次加载内存中的所有数据(这就是为什么我使用offset和limit)


有人知道我做错了什么,或者我如何才能做得更好吗?

任何可以通过限制和偏移(即提前停止执行)来完成的优化基本上都可以通过DISTINCE子句消除。这就是SQL查询执行计划中的distinct工作方式,与QueryDSL无关

<>你可以考虑在数据库中创建一个物化视图,它为这个投影索引不同的值,然后在QueDDSL中查询。物化视图跟踪不同的名称,这样就不必在查询时进行这种密集的计算。对于这种方法,您必须创建一个映射到物化视图的实体,但这是完全可能的

您可以使用以下方法为Oracle创建物化视图:

CREATE MATERIALIZED VIEW mv_names
REFRESH WITH ROWID 
AS SELECT  qTabA.col1, qTabB.col1, qTabC.col1, qTabC.col2 FROM tableA, tableB, tableC WHERE ...; 
然后在Querydsl中查询:

queryFactory.select(QNameView.nameView).from(QNameView.nameView)
    .offset(offset)
    .limit(limit)
    .fetch();

您也可以考虑对非常大的分页结果进行密钥集分页。因为非常大的偏移量也会影响查询性能(必须访问偏移量之前的任何内容才能跳过…)


为此,请对结果进行排序,并跟踪上次调用的最后一个名称。然后,只需添加一个where子句,消除任何低于该值的条目,这样就可以省略offset子句。确保在物化视图上对该列进行索引以获得最佳性能。

我发现使用
distinct
的查询比不使用
distinct
的相应查询速度慢,这并没有什么奇怪的。。。到底有什么东西不适合你呢?好像慢了20倍或者其他什么东西。像不可用的slow和比原生oraclesql查询慢得多@giorgigalimit和offset不是为了查询优化,而是为了java堆空间。如果我可以省略它们,我会的,但我不知道有什么办法不引起OutOfMemory错误。您的解决方案似乎很好,谢谢,但不幸的是不适合我的目的。偏移和限制条款的副作用是distinct条款失去了性能增益。您的查询不执行-period。它与Hibernate或QueryDSL无关。你自己看看如何使用JDBC查询或数据库shell。不,我的意思是我就是这样使用它们的。我必须使用它们,因为如果我不使用,我会遇到内存问题。是的,我有一个解决办法,但它很可怕,我问了一个问题,也许能找到一些有效的方法。感谢您的帮助尝试使用
iterate()
而不是
fetch()
。使用
iterate()。确保使用适当的查询处理程序(即
HibernateHandler
用于
HibernateQuery