业务系统中有个日志表,数据量每月百万条,每条数据包括三个大文本字段,类型为varchar(max),存放的是输入输出的报文数据,常常需要通过全匹配进行内容查询,也即是使用LIKE '%...%'。在文本内容较多的情况下,查询速度较慢,几十秒甚至几分钟都有可能。我一直在思考是否引入ES等搜索引擎工具,但是改动实在较大,有点小题大做了。老规矩,遇事不决问AI。
AI给出了几种方案,最优解应该是用全文索引。
全文目录是全文索引的容器,一个数据库可以有多个目录,一般创建一个默认目录即可:
-- 创建全文目录(若不存在)
IF NOT EXISTS (SELECT * FROM sys.fulltext_catalogs WHERE name = 'ftCatalog')
BEGIN
CREATE FULLTEXT CATALOG ftCatalog
WITH ACCENT_SENSITIVITY = OFF -- 不区分重音(根据需求调整)
AS DEFAULT; -- 设置为默认目录,后续创建索引可省略目录名
END
全文索引必须依赖表的唯一索引(一般是主键索引),且一次可针对多个字段创建:
-- 为 s_esb_log 表创建全文索引
IF NOT EXISTS (SELECT * FROM sys.fulltext_indexes WHERE object_id = OBJECT_ID('s_esb_log'))
BEGIN
CREATE FULLTEXT INDEX ON s_esb_log (
msg LANGUAGE 0, -- 0 = 非特定语言,减少分词拆分
sendmsg LANGUAGE 0,
remark LANGUAGE 0
)
KEY INDEX PK__s_esb_lo__3213E83F34120548 -- 依赖主键索引(需替换为实际主键索引名)
-- 若已设置默认目录,可省略 ON ftCatalog
WITH (
CHANGE_TRACKING = AUTO -- 自动跟踪数据变更(增删改后自动更新索引)
);
END“LANGUAGE 0“这个是重点,如果不加这个,查询时使用英文或数字组合会查不到数据。
业务系统是采用SSM框架开发,需要修改框架中对应的MyBatis配置文件:
//AND msg like '%${msg}%'
AND CONTAINS(msg, '"${msg}"')如上所示,将like语句改为CONTAINS语句。
改完重启并测试,发现根本查不到数据。
不要慌,系统在创建索引,100多G的表,创建索引要个把小时,不要像我当时一样,又不停的在找缘由,差点以为找错了方案。
索引创建好,重新在前端测试,查询速度基本达到秒级,客户再也不用盯着页面等半天了。