查询Oralce的一张表结构,在没有按照时间分区的场景下,跨度在两个月的时候的Explain就是table full,但是时间范围短的时候就正常使用时间索引,此表有130来万的数据,伪sql如下所示:
SELECT
*
FROM
tableName number_fpri
WHERE
number_fpri .INSERT_DATE BETWEEN TO_DATE( '2022-01-11 00:00:00', 'yyyy-MM-dd HH24:mi:ss' )
AND TO_DATE( '2023-01-11 23:59:59', 'yyyy-MM-dd HH24:mi:ss' )
Explain的结果如下:
解决方案:
替换掉TO_DATE函数,使用TO_CHAR函数替换,有朋友就会问了,有球用?
确实!
TO_CHAR改了是没有用的,需要新增TO_CHAR的函数索引
create index ind_date_to_char_flightdate on tableName (TO_CHAR(INSERT_DATE ,'yyyy-MM-dd HH24:mi:ss'));
然后修改sql为如下所示:
SELECT
*
FROM
tableName number_fpri
WHERE
TO_CHAR( number_fpri.INSERT_DATE , 'yyyy-MM-dd HH24:mi:ss' ) BETWEEN '2022-10-11 00:00:00'
AND '2023-01-11 23:59:59'
在某些情况下,使用 TO_DATE 函数可能会导致查询性能下降而无法使用索引,而使用 TO_CHAR 函数却可以使用索引提高查询性能。这通常是因为数据库中存储的日期格式与查询中使用的日期格式不同,或者因为日期格式化字符串不同,导致无法使用索引来加速查询。
例如,假设我们有一个 orders 表,其中包含一个 order_date 字段,数据类型为 DATE,存储的日期格式为 ‘YYYY-MM-DD HH24:MI:SS’。如果我们想要查询某一天的订单数量,并使用 TO_DATE 函数将字符串类型的参数转换为 DATE 类型,我们可以使用以下 SQL 语句:
SELECT COUNT(*) FROM orders WHERE order_date = TO_DATE('2022-06-26', 'YYYY-MM-DD');
在这个查询中,由于我们将字符串类型的参数转换为 DATE 类型,因此可以使用 order_date 上的索引来加速查询。然而,如果我们在查询中使用了不同的日期格式化字符串,就可能导致索引失效,从而无法使用索引来提高查询性能。
例如,以下 SQL 语句使用了不同的日期格式化字符串:
SELECT COUNT(*) FROM orders WHERE order_date = TO_DATE('2022/06/26', 'YYYY/MM/DD');
在这个查询中,由于使用了不同的日期格式化字符串,无法使用 order_date 上的索引来加速查询,而是需要进行全表扫描,从而影响查询性能。
如果我们使用 TO_CHAR 函数将 order_date 字段转换为字符串类型,并使用查询中使用的日期格式化字符串进行比较,我们就可以使用索引来提高查询性能。例如,以下 SQL 语句使用了 TO_CHAR 函数:
SELECT COUNT(*) FROM orders WHERE TO_CHAR(order_date, 'YYYY-MM-DD') = '2022-06-26';
在这个查询中,我们使用了 TO_CHAR 函数将 order_date 字段转换为字符串类型,并使用了查询中使用的日期格式化字符串进行比较。由于比较的是字符串类型的值,因此可以在转换后的字符串类型字段上创建索引,以提高查询性能。
总的来说,使用 TO_DATE 函数或 TO_CHAR 函数时,需要注意日期格式化字符串是否与数据库中存储的日期格式一致。如果日期格式不一致,可能会导致索引失效,从而无法使用索引来提高查询性能。