SQL性能调优
1.优化器提示
查询优化器会尝试执行最优的执行计划,但是如果用户能更深入地了解集群的数据设计、程序设计或数据分布,就可以通过 SQL 提示帮助优化器更合理地进行优化或更快地构建执行计划。
提示
SQL 提示是可选的,在某些场景可能会被跳过。
1.1.提示格式
SQL 提示由特殊注释 /*+ HINT */
定义,称为提示块
。提示名前后的空格是必需的,提示块必须放在运算符之后,一个关系运算符不支持多个提示。
示例:
sql
SELECT /*+ NO_INDEX */ T1.* FROM TBL1 where T1.V1=? and T1.V2=?
1.1.1.提示参数
如果需要,提示参数将放在提示名后的括号中,并用逗号分隔。
提示参数可以加引号,加引号的参数区分大小写,带引号和不带引号的参数不能是相同的提示定义。
示例:
sql
SELECT /*+ FORCE_INDEX(TBL1_IDX2,TBL2_IDX1) */ T1.V1, T2.V1 FROM TBL1 T1, TBL2 T2 WHERE T1.V1 = T2.V1 AND T1.V2 > ? AND T2.V2 > ?;
SELECT /*+ FORCE_INDEX('TBL2_idx1') */ T1.V1, T2.V1 FROM TBL1 T1, TBL2 T2 WHERE T1.V1 = T2.V1 AND T1.V2 > ? AND T2.V2 > ?;
1.2.提示错误
优化器会尽可能尝试启用每个提示及其参数。但是在如下场景中,它会跳过提示或提示参数:
- 不支持该提示;
- 未传入必要的参数;
- 提示不支持参数,但是传入了参数;
- 提示参数不正确或引用了不存在的对象,例如不存在的索引或表;
- 当前提示或当前参数与之前的不兼容,例如强制使用和禁用同一个索引。
1.3.支持的提示
1.3.1.FORCE_INDEX/NO_INDEX
强制或禁用索引扫描。
参数:
- 空,强制对每个基础表进行索引扫描,优化器将选择任何可用的索引,或者禁用所有索引;
- 使用某个索引名,或跳过此索引;
- 多个索引名,它们可以与不同的表相关,优化器将选择要扫描的索引或跳过所有索引。
示例:
sql
SELECT /*+ FORCE_INDEX */ T1.* FROM TBL1 T1 WHERE T1.V1 = T2.V1 AND T1.V2 > ?;
SELECT /*+ FORCE_INDEX(TBL1_IDX2, TBL2_IDX1) */ T1.V1, T2.V1 FROM TBL1 T1, TBL2 T2 WHERE T1.V1 = T2.V1 AND T1.V2 > ? AND T2.V2 > ?;
SELECT /*+ NO_INDEX */ T1.* FROM TBL1 T1 WHERE T1.V1 = T2.V1 AND T1.V2 > ?;
SELECT /*+ NO_INDEX(TBL1_IDX2, TBL2_IDX1) */ T1.V1, T2.V1 FROM TBL1 T1, TBL2 T2 WHERE T1.V1 = T2.V1 AND T1.V2 > ? AND T2.V2 > ?;
提示
查询不能同时具有 FORCE_INDEX
和 NO_INDEX
提示。
2.使用EXPLAIN PLAN FOR语句
Ignite 支持EXPLAIN PLAN FOR
语句,用于读取查询的执行计划。
可以使用该命令分析查询,然后做可能的优化,例如:
sql
EXPLAIN PLAN FOR SELECT name FROM Person WHERE age = 26;
解析的结果可能如下所示:
Exchange(distribution=[single]): rowcount = 1500.0, cumulative cost = IgniteCost [rowCount=11500.0, cpu=41500.0, memory=0.0, io=40000.0, network=6000.0], id = 47
TableScan(table=[[PUBLIC, PERSON]], tableId=[9], filters=[=($t1, 26)], projects=[[$t0]], requiredColumns=[{2, 3}]): rowcount = 1500.0, cumulative cost = IgniteCost [rowCount=10000.0, cpu=40000.0, memory=0.0, io=40000.0, network=0.0], id = 46
18624049226