JPA解决时间类型不一致导致索引不生效

简介: JPA解决时间类型不一致导致索引不生效

一 场景

在某一功能点击根据时间查询,查询速度达到2分钟,而且为单表查询,表数据量600w

二 验证问题

将sql在数据库可视化工具中执行,发现执行速度正常,而且走索引。但是,在应用中查询,却达到2分钟。

三 分析

在应用中查询应该没有走索引,因为字段为时间字段,那么很可能是在数据库做了函数转换。

四 解决

操作 1 在测试环境还原,测试环境该表数据量50w,体现不出加所以和不加索引的区别

操作 2 联系DBA DBA说存在,时间类型在数据库中增加了函数转换

操作 3 在测试环境数据库增加表 并设定为600w条数据

create table test_table as select rownum as id from xmltable('1 to 6000000');

alter table test_table add  (printed_Date DATE);

ALTER TABLE test_table ADD (IDENTITY_CARD VARCHAR2(20 CHAR));

ALTER TABLE test_table ADD (COMMITMENT_NC_CODE VARCHAR2(128 CHAR) );
COMMENT ON COLUMN test_table.COMMITMENT_NC_CODE IS '应收结算单位NC代码';

ALTER TABLE test_table ADD (CUSTOMS_NC_CODE VARCHAR2(128 CHAR) );
COMMENT ON COLUMN test_table.CUSTOMS_NC_CODE IS '供应商NC代码';

ALTER TABLE test_table ADD (COMMITMENT_NC_CODE VARCHAR2(128 CHAR) );
COMMENT ON COLUMN test_table.COMMITMENT_NC_CODE IS '应收结算单位NC代码';

ALTER TABLE test_table ADD (CUSTOMS_NC_CODE VARCHAR2(128 CHAR) );
COMMENT ON COLUMN test_table.CUSTOMS_NC_CODE IS '供应商NC代码';

ALTER TABLE test_table ADD (FREIGHT_TYPE VARCHAR2(128 CHAR) );
COMMENT ON COLUMN test_table.FREIGHT_TYPE IS '费用类别';

为表添加数据


这里可以设置不同时间
UPDATE test_table SET PRINTED_DATE = sysdate +10 WHERE ID > 1000000 and ID<3000000

为同一列不同行设置随机数
update test_table r 
set r.FREIGHT_TYPE = 
(select floor(dbms_random.value(100,99999999)) from dual)
where id > 2000000 and id<2100000

对printed_Date 添加索引  
CREATE INDEX IDX_test_table2 ON test_table (printed_date);

在java中增加实体类

/**
 * @author 子羽
 * @Description 测试实体类
 * @Date 2021/8/30
 */
@Entity
@Table(name = "TEST_TABLE")
public class TestTable {
    @Id
    @GeneratedValue(strategy =  GenerationType.AUTO)
    private String id;

    private Date printedDate;

    private String commitmentNcCode;


    private String freightType;

    -------
}

执行查询

SELECT *
FROM (
        SELECT *
        FROM test_table testtable0_
        WHERE 1 = 1
                AND testtable0_.printed_date >= TO_DATE('2017-08-31', 'yyyy-mm-dd')
                AND testtable0_.printed_date < TO_DATE('2021-09-30', 'yyyy-mm-dd')
        ORDER BY testtable0_.printed_date DESC
)
WHERE rownum <= 11;

在数据库可视化工具中查询 查询时间不到2s
在测试环境页面执行查询 查询时间接近6s

说明页面查询没有走索引

分析:jpa底层是orm框架,是不是时间属性的映射有问题,于是在时间属性printed_date上增加`
@Temporal(TemporalType.DATE)`注解

@Entity
@Table(name = "TEST_TABLE")
public class TestTable {
    @Id
    @GeneratedValue(strategy =  GenerationType.AUTO)
    private String id;
    
    @Temporal(TemporalType.DATE)
    private Date printedDate;

    private String commitmentNcCode;


    private String freightType;

    -----
}

在页面执行查询,查询时间不到2s,和数据库可视化工具查询时间一一致

进一步测试,删除索引

drop index  IDX_test_table2;

页面查询时间接近6s,完全证明页面查询走了索引。

结论

就算java中的属性是Date类型,也要在属性上标记 @Temporal(TemporalType.DATE),否则无法和数据库中的字段最映射,查询时会出现数据库隐形的函数转换,导致索引失效

相关文章
|
6月前
|
关系型数据库 MySQL 数据库
往数据库的字段varchar 或datetime里存时间值
往数据库的字段varchar 或datetime里存时间值
141 0
|
6月前
|
关系型数据库 MySQL
日期和时间类型
日期和时间类型。
59 2
|
存储 数据库 索引
一般会在什么样字段上添加什么样的索引
在数据库中,索引是一种用于加快数据检索速度的数据结构。通过在特定的字段上创建索引,可以大幅度提高查询效率。然而,不是所有的字段都适合创建索引,因为索引的创建和维护也会带来额外的开销。在选择字段创建索引时,需要综合考虑数据的查询频率、数据的更新频率以及索引的存储和性能开销等因素。下面将介绍一些常见的字段类型和索引的选择策略。
191 1
|
SQL 索引
SQL查看表字段信息如:字段名、字段类型、字段精度、字段大小、索引、主键等
表名、字段名、字段类型、字段精度、字段大小 字段名、是否为主键、字段类型、字段大小、索引名
1240 0
SQL查看表字段信息如:字段名、字段类型、字段精度、字段大小、索引、主键等
|
存储 关系型数据库 MySQL
列的类型定义——日期和时间类型
前言 日期与时间类型是为了方便在数据库中存储日期和时间而设计的,数据库有多种表示日期和时间的数据类型。其中,YEAR类型表示年,DATE类型表示日期,TIME类型表示时间,DATETIME和TIMESTAMP表示日期和时间。下面从这5种日期与时间类型的字节数、取值范围和零值等方面进行对比,如下表所示。
|
SQL 关系型数据库 MySQL
MySql格式化日期和 时间( timestamp),自定义时间函数快速格式化 年月日,时分秒【注意SQL中大小写】
MySql格式化日期和 时间( timestamp),自定义时间函数快速格式化 年月日,时分秒【注意SQL中大小写】
438 0
MySql格式化日期和 时间( timestamp),自定义时间函数快速格式化 年月日,时分秒【注意SQL中大小写】
|
关系型数据库 MySQL PHP
MySQL数据库(9):数据类型-时间日期类型
MySQL数据库(9):数据类型-时间日期类型
150 0
MySQL数据库(9):数据类型-时间日期类型
|
编解码
时间类型
时间类型
158 0
|
数据库
列的数据类型讲解
列的数据类型讲解
|
存储 Unix 关系型数据库
关于日期及时间字段的查询
在项目开发中,一些业务表字段经常使用日期和时间类型,而且后续还会牵涉到这类字段的查询。关于日期及时间的查询等各类需求也很多,本篇文章简单讲讲日期及时间字段的规范化查询方法。
292 0
关于日期及时间字段的查询