在使用Lindorm SQL查询宽表数据或创建索引时,可能会遇到报错或出现查询性能不符合预期的情况。本文介绍Lindorm SQL使用时的常见问题和解决方案。
本文列举的常见问题仅适用于宽表引擎。
如何解决或规避低效查询问题?
什么是低效查询?低效查询有哪些特点?
如果查询语句中带有过滤条件,但该过滤条件无法有效地利用已有的主键或索引,导致查询时必须扫描全表,这样的查询被视为低效查询。
如果执行查询语句后,宽表引擎报错This query may be a full table scan and thus may have unpredictable performance
,表示该查询是低效查询。假设test表的联合主键由p1,p2,p3三个列组成,p1列是主键的第一列,查询条件为SELECT * FROM test WHERE p2=10;
。此时查询条件中未包含第一个主键列p1,因此该查询语句会被认定为低效查询语句。
由于低效查询可能会带来性能稳定性风险,默认情况下Lindorm会检测并阻止低效查询的执行。
查询条件WHERE中的列是主键列或索引列,为什么查询还是触发了低效查询异常?
宽表引擎的主键、二级索引和MySQL联合索引的匹配规则类似,均遵循最左匹配原则,即在多个列组成的联合主键或索引中,系统从主键或索引键的第一列(最左侧列)开始逐一与查询条件中的列进行匹配。如果查询条件中不包含主键或索引键的第一列,则此时查询仍不会命中主键或二级索引,导致查询仍然是低效查询。
假设test表的主键由p1、p2、p3三个列组成,p1列是主键的第一列,根据最左匹配原则,查询数据时系统将从p1列开始匹配。如果查询条件中未包含p1列,例如SELECT * FROM test WHERE p2<30;
,此时无法匹配到主键第一列p1,系统不会命中主键进而查询全表数据以满足查询条件p2<30
。
如何规避低效查询?
以下是业务中规避低效查询的一些推荐的方法:
使用GROUP BY查询时报错The diff group keys of subPlan is over lindorm.aggregate.subplan.groupby.keys.limit=..., it may cost a lot memory so we shutdown this SubPlan
?
原因:
GROUP BY
操作形成的分组数过多,可能消耗了大量的内存资源,从而加重实例负载,因此宽表引擎限制了结果集中分组数过大的查询。
解决方案:
在查询语句中添加过滤条件,减少最终分组数。
联系Lindorm技术支持(钉钉号:s0s3eg3)调大分组数的阈值。
重要调大分组数的阈值可能会影响实例的稳定性。
针对多维查询匹配场景,建议使用搜索索引。详细介绍,请参见搜索索引介绍。
对开启动态列的表执行SELECT *
查询报错Limit of this select statement is not set or exceeds config when select all columns from table with property DYNAMIC_COLUMNS=true
?
原因:
开启动态列的表可能包含大量的动态列,且表的Schema定义不固定。如果对这类表进行全表扫描,将会导致IO消耗严重,加重实例负载。为避免高负载情况的产生,Lindorm宽表引擎对动态列表的查询语句进行了限制。
解决方案:
在SELECT语句中添加LIMIT子句,限制返回结果的数量。例如SELECT * FROM test LIMIT 10;
。
为什么创建二级索引时报错Executing job number exceed, max job number = 8
?
原因:
一个实例中仅允许同时存在8个二级索引的构建任务。如果某一时刻二级索引的构建任务数已达8个,则再次创建新的二级索引时,创建语句将会报错。
解决方案:
建议您避免同时创建大量二级索引。如果有大量创建的需求,请联系Lindorm技术支持(钉钉号:s0s3eg3)。
在宽表引擎上已执行删除列操作,为什么重新添加同名列时会报错column is under deleting
?
原因:
为避免由于数据类型等因素引发的脏数据问题,在您执行删除列的操作后,宽表引擎还需要异步清理内存、热存储和冷存储上该列的数据。在数据全部清理完之前,系统不允许重新添加同名的新列。
解决方案:
由于数据清理由系统自行完成,可能会消耗很长时间。建议您通过以下方式加速数据的清理过程,待数据清理完成之后重新添加同名列。
假设执行了删除列操作的表名为dt
:
-- 执行FLUSH操作,强制将内存中残留的数据刷到存储媒介上
ALTER TABLE dt FLUSH;
-- 执行COMPACTION操作,执行数据的合并和删除
ALTER TABLE dt COMPACT;
FLUSH
语法从SQL引擎2.7.1版本开始支持。如何查看SQL引擎的版本,请参见SQL版本说明。FLUSH
操作和COMPACT
操作是异步操作。语句执行成功并不代表数据清理完成,需要等待一段时间才能彻底清理完成。对数据量大的表执行
COMPACT
操作,其执行期间会占用较多系统资源,因此不建议在业务高峰期执行。
创建二级索引后,写入数据时为什么会报错Performing put operations with User-Defined-Timestamp in indexed column on MULTABLE_LATEST table is unsupported
?
原因:
如果写入时显式指定了自定义时间戳(例如,使用UPSERT语句写入数据时,通过/*+ _l_ts */
指定了自定义时间戳),此时要求主表与二级索引表之间的可变性(Mutability)必须是MULTABLE_ALL
。但是出于性能考虑,Lindorm系统默认将主表与索引表的可变性配置为MULTABLE_LATEST
,在这种配置下创建二级索引并启用会触发可变性约束限制,导致报错。
解决方案:
由于创建索引表后MUTABILITY参数的值不支持修改,因此您需要先删除原有的二级索引。
删除主表中原有的二级索引。
-- 禁用原有二级索引 ALTER INDEX IF EXISTS <原有二级索引名> ON <主表名> DISABLED; -- 删除原有二级索引 DROP INDEX IF EXISTS <原有二级索引名> ON <主表名>;
DROP INDEX
语法的详细介绍,请参见删除二级索引。将主表的MUTABILITY属性的值修改为
MUTABLE_ALL
。ALTER TABLE IF EXISTS <主表名> SET MUTABILITY='MUTABLE_ALL';
创建新的二级索引,并写入数据。创建二级索引的语法说明,请参见CREATE INDEX。
说明自定义时间戳的写入方式,请参见通过HINT设置时间戳实现多版本数据管理。
二级索引可变性约束与自定义时间戳的关系,请参见更新自定义时间戳的索引。