有没有办法在涉及存储函数时提高Hibernate生成的查询的性能?

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

我有一个页面以分页的方式显示网格中的一些记录。我有表my_table和实体MyTable链接到它:

@SuppressWarnings("serial")
@Entity
@Table(name="my_table")
@Inheritance(strategy=InheritanceType.JOINED)
public class MyTable extends BaseEntity implements Auditable, Serializable {
    //...
    private Integer myAttribute; //This does not exist in the table
    //...
    @Formula(value = "(myFunction(attr1, attr2))")
    public Integer getMyAttribute() {
        return myAttribute;
    }

    public void setMyAttribute(Integer myAttribute) {
        this.myAttribute = myAttribute;
    }
    //...
}

当我打算通过“普通”字段进行查询时,一切都很有效,但是当我尝试按myAttribute过滤时,例如:

queryInput.addAndCriterion(Restrictions.eq("myAttribute", v));

例如,v是一个值为123的Integer,搜索将会超时。如果我直接在MySQL中运行存储的函数,那么它会立即执行。我认为这段代码会对每个项目发送一个单独的请求,这可以解释问题。有没有办法确保我可以通过我的存储函数以高效的方式进行过滤(可能会在查询中生成对存储函数的调用)?我需要定义一个标准,规定每个记录需要调用一个存储的函数,并传递attr1attr2,这些是记录的字段?

java mysql performance hibernate stored-functions
1个回答
1
投票

如下面的评论中所述,这个答案并没有解决Hibernate故障排除的问题,但是无论如何OP都喜欢它。

答案如下......


查询任何函数,存储函数或内置函数始终是表扫描。

例如,即使存在一个索引,也无法在create_date上使用索引:

SELECT * FROM MyTable WHERE MONTH(create_date) = 2

任何时候使用索引列作为函数的参数都是如此。

MySQL 5.7及更高版本的解决方法是对该表达式使用generated column,然后为生成的列编制索引。

ALTER TABLE MyTable
  ADD COLUMN created_month INT AS (MONTH(create_date)),
  ADD INDEX (created_month);

一旦你这样做,你可以查询created_month = 2或者你甚至可以查询原始表达式MONTH(create_date) = 2,它将使用索引。

不幸的是,只有内置的MySQL函数才能使用此功能。

https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html说:

生成的列表达式必须遵守以下规则。如果表达式包含不允许的构造,则会发生错误。

  • 不允许存储函数和用户定义的函数。

另一种解决方案是为您创建一个新的具体列来存储存储函数的结果,假设该值是从其参数确定的,并且不依赖于其他表中的数据状态。

ALTER TABLE MyTable
  ADD COLUMN myAttribute INT,
  ADD INDEX (myAttribute);

CREATE TRIGGER att_ins BEFORE INSERT ON MyTable 
FOR EACH ROW SET NEW.myAttribute = MyFunction(NEW.attr1, NEW.attr2);

CREATE TRIGGER att_upd BEFORE UPDATE ON MyTable 
FOR EACH ROW SET NEW.myAttribute = MyFunction(NEW.attr1, NEW.attr2);

然后,您将查询新列而不是表达式。

这有点麻烦,但这是对存储函数的结果进行索引查找的唯一方法。

© www.soinside.com 2019 - 2024. All rights reserved.