慢查询 大文本字段longtext查询问题

【 TiDB 使用环境】测试
【 TiDB 版本】V7.1.2
【复现路径】
T表 TS_DOCKPF_RECORD 数据量 :5581条 T1表 TS_DOCKPF 数据量 :22条

T表中 字段 RECORD_REQ和RECORD_RES 是longtext类型。每一条数据中这两个字段的存储的内容大概180kb左右。

执行如下sql :
EXPLAIN ANALYZE SELECT
T.DOCKPF_ID AS “fkByDockpfId.rid”,
T.BUS_TYPE AS busType,
T.RECORD_UID AS recordUid,
T.RECORD_REQ AS recordReq,
** T.RECORD_RES AS recordRes,**
T.DOCK_CONTENT AS dockContent,
T.RECORD_STATE AS recordState,
T.RECORD_TIME AS recordTime,
T.RID AS rid,
T.IF_DELETE AS ifDelete
FROM
TS_DOCKPF_RECORD T
LEFT JOIN TS_DOCKPF T1 ON T1.RID = T.DOCKPF_ID
WHERE
T1.UID = ‘78AA82AA0C01474C88238161234567890’
AND T.BUS_TYPE = 31
AND T.RECORD_STATE = 0
AND T.IF_DELETE = 0
ORDER BY
T.MODIFY_TIME ASC,
T.RID ASC
LIMIT
10;

执行耗时30s+

如果将查询结果字段中去掉两个大字段的查询
sql如下:
EXPLAIN ANALYZE SELECT
T.DOCKPF_ID AS “fkByDockpfId.rid”,
T.BUS_TYPE AS busType,
T.RECORD_UID AS recordUid,
T.DOCK_CONTENT AS dockContent,
T.RECORD_STATE AS recordState,
T.RECORD_TIME AS recordTime,
T.RID AS rid,
T.IF_DELETE AS ifDelete
FROM
TS_DOCKPF_RECORD T
LEFT JOIN TS_DOCKPF T1 ON T1.RID = T.DOCKPF_ID
WHERE
T1.UID = ‘78AA82AA0C01474C88238161234567890’
AND T.BUS_TYPE = 31
AND T.RECORD_STATE = 0
AND T.IF_DELETE = 0
ORDER BY
T.MODIFY_TIME ASC,
T.RID ASC
LIMIT
10;
执行耗时 30ms

两次执行计划
bbb.sql (27.2 KB)

对于这种大字段查询的耗时,请教各位大神,如何优化?

俩思路
1、如果sql中的order by字段可以去掉,那就去掉,应该会快
2、在sql2的快的基础上,select字段中写标量子查询,根据表的pk再回表T中反查两个大字段

得具体看看 slow log,有 longtext 大字段的话,可能 parser 会慢。
你这两个执行计划其实是相同的。

你这数据太大了,大部分消耗是在数据传输了,哪个人设计的存这么大数据的拉出去砍了吧。

两个执行计划看着是相同的,但是你看Selection_25(Probe)这个算子的execution info scan_detail扫描的key是不带大字段的很多倍,这个有点不太正常,翻了下文档也没有找到对于大字段的存储方式,看有没有大佬知道这个跟正常存储有没有区别

外面再套一层,当前结果集只要T表的主键结果集做c表,再关联T表查要的数据试一下(先查limit 10的主键再去拿10条数据)

我建议你用SQL_NO_CACHE再试一下两个sql,我感觉是缓存有干扰

slow.log (7.4 KB)
带有大字段查询的 slow log

数据太大了

1.sql中的order by字段可以去掉,速度并没什么提升。问题还是在大字段上。
2.我们目前修改的方案也是使用PK回表反查T表limit10的数据。只是在想有没有什么更优的优化方案。

你在dashboard慢查询中可以看到哪个阶段慢。

两个执行计划都拿下来看下呗

带有大字段 没有大字段 不带排序和回表反查的相关执行计划
执行计划.sql (56.7 KB)

嗯,这个场景去除order by确实用处不大,原因是TS_DOCKPF_RECORD做完过滤后只有1条

大字段的查询快不了,内存使用高

几个大字段类型数据的优化,有以下几点思路,思路的最终目的还是减少内存使用率和提高命中率
1.万能万金油:索引,给这个字段加索引,对长字段,考虑前缀索引或者全文索引
2.如果你只查询此长字段里部分内容,可以考虑使用分页查询,减少查询时间
3.查询优化:看看SQL能不能继续优化,规避全表扫描
4.数据库分库分表:可以考虑分库分表,避免全扫
5.缓存技术加持:可以考虑使用redis、memcached等,将结果缓存起来,减少对数据库的访问,节省资源消耗

内存使用高

数据量太多了,建议优化下