TiDB 执行SQL一直卡住

【TiDB 使用环境】生产环境
【TiDB 版本】
【操作系统】
【部署方式】
【集群数据量】
【集群节点数】
【问题复现路径】

  where i_date in (
                            select  max(I_DATE) I_DATE
                        from dim_date_month_dmi
                        where I_DATE >= ?
                        and I_DATE < ? and i_date>=20250428
                        group by DATE_FORMAT(D_DATE, '%Y')
                )  [20250331 20250430]

【遇到的问题:问题现象及影响】
这种方式提交查询,tidb卡住,不报错,也不返回,如果jdbc url参数添加interpolateParams=true,就能立马执行出来

如果代码里面手动把“?”替换为对应日期,也能立马能查出来

下面这样就很快

  where i_date in (
                            select  max(I_DATE) I_DATE
                        from dim_date_month_dmi
                        where I_DATE >= 20250331
                        and I_DATE < 20250430 and i_date>=20250428
                        group by DATE_FORMAT(D_DATE, '%Y')
                ) 
下面这样也很快,总之只要不传“?”这种预编译,就很快
and I_DATE >= DATE_FORMAT(last_day(date_sub(current_date ,interval 1 month)),'%Y%m%d')
                                and I_DATE < DATE_FORMAT(current_date,'%Y%m%d')

注意上面只是片段
【资源配置】进入到 TiDB Dashboard -集群信息 (Cluster Info) -主机(Hosts) 截图此页面
【复制黏贴 ERROR 报错的日志】
【其他附件:截图/日志/监控】

:yum:这个我遇到过,这种写法不走索引,要加引号才走索引。

1 个赞

因为隐式转换?

是的,因为隐式转换。执行计划的operator info里有描述,进行了cast转换,索引列使用函数后,就不会走索引了。

应该不是,估计是编译的问题

:flushed:你发的前后对比,和我发的示例不是一样么?

这个写法等同于 '2025-03-31',是带引号的。

DATE_FORMAT(last_day(date_sub(current_date ,interval 1 month)),‘%Y%m%d’)

你发的是在客户端已经替换了,我发的是?号的形式,提交到服务端,服务端来处理的

:yum:服务端处理的时候,让他加上引号。

这种也很快,就是不管用不用引号,只要是写死的,都很快,如果预编译就不行了

 where i_date in (
                            select  max(I_DATE) I_DATE
                        from dim_date_month_dmi
                        where I_DATE >= 20250331
                        and I_DATE < 20250430 and i_date>=20250428
                        group by DATE_FORMAT(D_DATE, '%Y')
                ) 

I_DATE 是什么类型

:flushed:我知道了,你的I_DATE是int类型的吧。

int类型

嗯,int类型

哦,那这个和我那个是反着的,我那个是日期类型,得加引号,这个是int类型,不加引号。

:flushed:这种写法在查询分析器客户端里能执行么?

一般不都是这么预编译吗
db.Queryx('where i_date in (
select max(I_DATE) I_DATE
from dim_date_month_dmi
where I_DATE >= ?
and I_DATE < ? and i_date>=20250428
group by DATE_FORMAT(D_DATE, ‘%Y’)
) ', 20250331, 20250430)

哦哦,程序啊。 能跟踪一下tidb,看看数据库里真实执行的语句是怎样的么?

我来,自研审计工具刚好能用

提交到服务端的就是上面这种带?号的,
如果加这个参数interpolateParams=true,提交到服务端的就不带问号了

https://docs.pingcap.com/zh/tidb/stable/sql-statement-prepare/#prepare

可以用prepare语句模拟一下这种带?的sql,看看是不是还是慢了。

prepare testsql from 'select DATE_FORMAT(?, '%Y') ';

set @date1=‘2024-01-01’;

execute testsql USING @date1;

类似这样