Hibernate 查询中的 Mysql 索引提示

问题描述 投票:0回答:4

我们如何在Hibernate查询中指定Mysql索引提示?

在查询规划器没有选择正确索引的情况下,在 Mysql 查询中使用索引提示就变得势在必行(参考:https://www.percona.com/blog/2012/12/14/the-optimization-that-often-不是索引合并交集/)。

这可以通过此处指定的原始查询轻松完成:https://dev.mysql.com/doc/refman/5.7/en/index-hints.html

mysql hibernate indexing query-planner
4个回答
1
投票

在 Hibernate 5 中,您可以使用 org.hibernate.query.Query.html#addQueryHint 定义底层数据库的查询提示。所使用的 SQL 方言负责注入与查询中定义的每个提示相关的适当文本。

不幸的是,如果您阅读 org.hibernate.dialect.MySQLDialect 的源代码,您会注意到它没有扩展方法 org.hibernate.dialect.Dialect#getQueryHintString,并且默认情况下不执行任何操作。

您可以尝试寻找一些替代的 MySQL 方言来实现有关索引的数据库查询提示,或者,如果您愿意亲自动手,您可以扩展其中一种 MySQL 方言并自己完成:

public class MySqlExtendedDialect extends MySQLDialect {

    public String getQueryHintString(String query, List<String> hints) {
       /** define a format and read the hints, then patch the query appropriately **/
        String modifiedQuery = query;
        return modifiedQuery;
    }

}

例如,您可以在查询中定义“USE_INDEX_COL1_COL2”等提示。然后,当你的方言找到“USE_INDEX_*”提示时,它需要进行一些基本的 SQL 解析,并在正确的位置注入正确的文本。

纯粹的乐趣!


1
投票

我无法使用此方法,未调用“getQueryHintString”方法。

现在遵循此处描述的解决方案:

如何在 Hibernate criteria api 查询中插入“优化器提示”

实现了 Hibernate 拦截器,效果很好。


1
投票

从 Hibernate 5.2.12 开始,MySQL 现在也支持使用 org.hibernate.query.Query.html#addQueryHint 方法进行查询提示。


0
投票

Query.addQueryHint
为我工作:

session.createQuery(myCriteriaQuery)
  .addQueryHint("USE INDEX 'MyIndex' ON TABLE 'MyTable'")

例如

CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery(MyEntity.class);
Root<MyEntity> folderRoot = cq.from(MyEntity.class);
Join<MyEntity, MyRelatedEntity> myRelatedEntityJoin = 
folderRoot.join("MyRelatedEntity", JoinType.LEFT);

cq.where(cb.equal(folderRoot.get("relatedEntity")
  .get("relatedEntityId"), 123L));

TypedQuery<MyEntity> q = session.createQuery(cq)
  .addQueryHint("USE INDEX 'MyIndex' ON TABLE 'MyTable'")

List<MyEntity> result = q.getResultList();
© www.soinside.com 2019 - 2024. All rights reserved.