优化使用Like运算符的SKU查询性能问题求助
针对SKU模糊查询的性能优化方案
我太懂这种全表扫描拖垮性能的痛苦了——42万行数据每次都全扫,TrueSight报性能差完全是意料之中的。结合你的代码和场景,给你几个实打实的优化方向:
优化索引是最直接的解法
- 如果你的业务场景里,
sku的查询大多是前缀匹配(比如用户输入的是'SKU123%'这种开头固定的格式),那赶紧给sku加个普通B-tree索引,再把item_status也加到索引里,做成复合索引(item_status, sku)。这样数据库会先过滤掉item_status = 3的行,再利用索引快速定位匹配前缀的SKU,直接跳过全表扫描的步骤。 - 如果是后缀或中间匹配(比如
'%123'或者'%ABC%'),B-tree索引就派不上用场了,这时候可以试试数据库的全文索引。比如MySQL可以给sku字段创建FULLTEXT索引,然后把查询语句改成MATCH(sku) AGAINST(?);PostgreSQL可以用tsvector和tsquery来实现全文检索,速度比like快不止一个量级。
- 如果你的业务场景里,
调整查询逻辑,减少不必要的扫描
- 尽量引导业务端使用前缀匹配,毕竟前缀匹配能用上索引,性能提升最明显。如果业务上必须支持任意位置的模糊查询,全文索引是最优解。
- 要是不需要实时数据,可以考虑缓存常用查询结果,比如用Redis把高频查询的SKU结果存起来,或者定期生成一个包含活跃SKU的视图,避免每次都去扫全表。
数据库层面的小调整
- 检查下
descrip表的统计信息是不是过时了,有些数据库(比如Oracle、SQL Server)如果统计信息太久没更新,优化器可能会选错执行计划,更新统计信息后说不定就能自动用上索引了。 - 要是未来数据量还会增长,提前考虑分表分库,比如按SKU的前缀或者item_status来拆分表,每次查询只扫其中一个小表,性能自然就上去了。
- 检查下
你的当前查询代码:
public SkuQuery(final DataSource ds) { super(ds, "SELECT sku, description1, buyer, analyst FROM descrip WHERE item_status != 3 AND sku like ? "); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); }
举个例子,如果用复合索引的话,不需要改代码,只要执行创建索引的语句就行:
CREATE INDEX idx_descrip_status_sku ON descrip(item_status, sku);
如果用全文索引,就需要修改SQL语句,比如MySQL下改成:
SELECT sku, description1, buyer, analyst FROM descrip WHERE item_status != 3 AND MATCH(sku) AGAINST(? IN BOOLEAN MODE);
内容的提问来源于stack exchange,提问作者Samarland




