云服务器内容精选

  • 检查隐式转换的性能问题 在某些场景下,数据类型的隐式转换可能会导致潜在的性能问题。请看如下的场景: SET enable_fast_query_shipping = off; CREATE TABLE t1(c1 VARCHAR, c2 VARCHAR); CREATE INDEX on t1(c1); EXPLAIN verbose SELECT * FROM t1 WHERE c1 = 10; 上述查询的执行计划如下: c1的数据类型是varchar,当查询的过滤条件为c1 = 10时,优化器默认将c1隐式转换为bigint类型,导致两个后果: 不能进行DN裁剪,计划下发到所有DN上执行。 计划中不能使用Index Scan方式扫描数据。 这会引起潜在的性能问题。 当知道了问题原因后,可以做针对性的SQL改写。对于上面的场景,只要将过滤条件中的常量显示转换为varchar类型,结果如下: EXPLAIN verbose SELECT * FROM t1 WHERE c1 = 10::varchar; 为了提前识别隐式类型转换可能带来的性能影响, GaussDB 提供了一个guc option:check_implicit_conversions。打开该参数后,对于查询中出现的隐式类型转换的索引列,在路径生成阶段进行检查,如果发现索引列没有生成候选的索引扫描路径,则会通过报错的形式提示给用户。举例如下: SET check_implicit_conversions = on; SELECT * FROM t1 WHERE c1 = 10; ERROR: There is no optional index path for index column: "t1"."c1". Please check for potential performance problem. 参数check_implicit_conversions只用于检查隐式类型转换引起的潜在性能问题,在正式生产环境中请关闭该参数(该参数默认关闭)。 在将check_implicit_conversions打开时,必须同时关闭enable_fast_query_shipping参数,否则由于后一个参数的作用,无法查看对隐式类型转换修复的结果。 一个表的候选路径可能包括seq scan和index scan等多个可能的数据扫描方式,最终执行计划使用的表扫描方式是由执行计划的代价来决定的,因此即使生成了索引扫描的候选路径,也可能生成的最终执行计划中使用其它扫描方式。 父主题: SQL调优指南
  • 调优手段之GUC参数 查询优化的主要目的是为查询语句选择高效的执行方式。 如下SQL语句: 1 2 select count(1) from customer inner join store_sales on (ss_customer_sk = c_customer_sk); 在执行customer inner join store_sales的时候,GaussDB支持Nested Loop、Merge Join和Hash Join三种不同的Join方式。优化器会根据表customer和表store_sales的统计信息估算结果集的大小以及每种Join方式的执行代价,然后对比选出执行代价最小的执行计划。 正如前面所说,执行代价计算都是基于一定的模型和统计信息进行估算,当因为某些原因代价估算不能反映真实的cost的时候,就需要通过GUC参数设置的方式让执行计划倾向更优规划。例如:random_page_cost参数表示优化器计算一次非顺序抓取磁盘页面的开销,该参数默认值为4。当机器磁盘随机读取的速度较快时,比如SSD设备,可以将该参数的值适当调小,更改后,索引扫描的代价降低,生成计划时更倾向于选择索引扫描的方式。
  • 调优手段之统计信息 GaussDB优化器是典型的基于代价的优化 (Cost-Based Optimization,简称CBO)。在这种优化器模型下,数据库根据表的元组数、字段宽度、NULL记录比率、distinct值、MCV值、HB值等表的特征值,以及一定的代价计算模型,计算出每一个执行步骤的不同执行方式的输出元组数和执行代价(cost),进而选出整体执行代价最小/首元组返回代价最小的执行方式进行执行。这些特征值就是统计信息。从上面描述可以看出统计信息是查询优化的核心输入,准确的统计信息将帮助规划器选择最合适的查询规划,一般来说我们通过analyze语法收集整个表或者表的若干个字段的统计信息,周期性地运行ANALYZE,或者在对表的大部分内容做了更改之后马上运行它是个好习惯。 注意,DDL可能会导致统计信息发生变化,进而导致计划跳变。当表上做了DDL操作后,应注意统计信息是否需要重新收集。
  • 背景信息 ANALYZE语句可收集与数据库中表内容相关的统计信息,统计结果存储在系统表PG_STATISTIC中。查询优化器会使用这些统计数据,以生成最有效的执行计划。 建议在执行了大批量插入/删除操作后,例行对表或全库执行ANALYZE语句更新统计信息。目前默认收集统计信息的采样比例是30000行(即:guc参数default_statistics_target默认设置为100),如果表的总行数超过一定行数(大于1600000),建议设置guc参数default_statistics_target为-2,即按2%收集样本估算统计信息。 对于在批处理脚本或者存储过程中生成的中间表,也需要在完成数据生成之后显式的调用ANALYZE。
  • 操作步骤 收集SQL中涉及到的所有表的统计信息。在数据库中,统计信息是规划器生成计划的源数据。没有收集统计信息或者统计信息陈旧往往会造成执行计划严重劣化,从而导致性能问题。从经验数据来看,10%左右性能问题是因为没有收集统计信息。具体请参见更新统计信息。 通过查看执行计划来查找原因。如果SQL长时间运行未结束,通过EXPLAIN命令查看执行计划,进行初步定位。如果SQL可以运行出来,则推荐使用EXPLAIN ANALYZE或EXPLAIN PERFORMANCE查看执行计划及实际运行情况,以便更精准地定位问题原因。有关执行计划的详细介绍请参见SQL执行计划介绍。 审视和修改表定义。 针对EXPLAIN或EXPLAIN PERFORMANCE信息,定位SQL慢的具体原因以及改进措施,具体参见典型SQL调优点。 通常情况下,有些SQL语句可以通过查询重写转换成等价的,或特定场景下等价的语句。重写后的语句比原语句更简单,且可以简化某些执行步骤达到提升性能的目的。查询重写方法在各个数据库中基本是通用的。经验总结:SQL语句改写规则介绍了几种常用的通过改写SQL进行调优的方法。
  • 调优手段之统计信息 GaussDB优化器是典型的基于代价的优化 (Cost-Based Optimization,简称CBO)。在这种优化器模型下,数据库根据表的元组数、字段宽度、NULL记录比率、distinct值、MCV值、HB值等表的特征值,以及一定的代价计算模型,计算出每一个执行步骤的不同执行方式的输出元组数和执行代价(cost),进而选出整体执行代价最小/首元组返回代价最小的执行方式进行执行。这些特征值就是统计信息。从上面描述可以看出统计信息是查询优化的核心输入,准确的统计信息将帮助优化器选择最合适的查询规划,一般来说我们通过analyze语法收集整个表或者表的若干个字段的统计信息,周期性地运行ANALYZE,或者在对表的大部分内容做了更改之后马上运行它是个好习惯。 DDL可能会导致统计信息发生变化,进而导致计划跳变。当表上做了DDL操作后,应注意统计信息是否需要重新收集。
  • 调优手段之GUC参数 查询优化的主要目的是为查询语句选择高效的执行方式。 如下SQL语句: 1 2 select count(1) from customer inner join store_sales on (ss_customer_sk = c_customer_sk); 在执行customer inner join store_sales的时候,GaussDB支持Nested Loop、Merge Join和Hash Join三种不同的Join方式。优化器会根据表customer和表store_sales的统计信息估算结果集的大小以及每种Join方式的执行代价,然后对比选出执行代价最小的执行计划。 正如前面所说,执行代价计算都是基于一定的模型和统计信息进行估算,当因为某些原因代价估算不能反映真实的cost的时候,我们就需要通过GUC参数设置的方式让执行计划倾向更优规划。例如:random_page_cost参数表示优化器计算一次非顺序抓取磁盘页面的开销,该参数默认值为4。当机器磁盘随机读取的速度较快时,比如SSD设备,可以将该参数的值适当调小,更改后,索引扫描的代价降低,生成计划时更倾向于选择索引扫描的方式。
  • 调优手段之GUC参数 查询优化的主要目的是为查询语句选择高效的执行方式。 如下SQL语句: 1 2 select count(1) from customer inner join store_sales on (ss_customer_sk = c_customer_sk); 在执行customer inner join store_sales的时候,GaussDB支持Nested Loop、Merge Join和Hash Join三种不同的Join方式。优化器会根据表customer和表store_sales的统计信息估算结果集的大小以及每种Join方式的执行代价,然后对比选出执行代价最小的执行计划。 正如前面所说,执行代价计算都是基于一定的模型和统计信息进行估算,当因为某些原因代价估算不能反映真实的cost的时候,我们就需要通过GUC参数设置的方式让执行计划倾向更优规划。例如:random_page_cost参数表示优化器计算一次非顺序抓取磁盘页面的开销,该参数默认值为4。当机器磁盘随机读取的速度较快时,比如SSD设备,可以将该参数的值适当调小,更改后,索引扫描的代价降低,生成计划时更倾向于选择索引扫描的方式。
  • 调优手段之统计信息 GaussDB优化器是典型的基于代价的优化 (Cost-Based Optimization,简称CBO)。在这种优化器模型下,数据库根据表的元组数、字段宽度、NULL记录比率、distinct值、MCV值、HB值等表的特征值,以及一定的代价计算模型,计算出每一个执行步骤的不同执行方式的输出元组数和执行代价(cost),进而选出整体执行代价最小/首元组返回代价最小的执行方式进行执行。这些特征值就是统计信息。从上面描述可以看出统计信息是查询优化的核心输入,准确的统计信息将帮助优化器选择最合适的查询规划,一般来说我们通过analyze语法收集整个表或者表的若干个字段的统计信息,周期性地运行ANALYZE,或者在对表的大部分内容做了更改之后马上运行它是个好习惯。 DDL可能会导致统计信息发生变化,进而导致计划跳变。当表上做了DDL操作后,应注意统计信息是否需要重新收集。
  • 检查隐式转换的性能问题 在某些场景下,数据类型的隐式转换可能会导致潜在的性能问题。请看如下场景: SET enable_fast_query_shipping = off; CREATE TABLE t1(c1 VARCHAR, c2 VARCHAR); CREATE INDEX on t1(c1); EXPLAIN verbose SELECT * FROM t1 WHERE c1 = 10; 上述查询的执行计划如下: c1的数据类型是varchar,当查询的过滤条件为c1 = 10时,优化器默认将c1隐式转换为bigint类型,导致两个后果: 不能进行DN裁剪,计划下发到所有DN上执行。 计划中不能使用Index Scan方式扫描数据。 这会引起潜在的性能问题。 当知道了问题原因后,可以做针对性的SQL改写。对于上述场景,只要将过滤条件中的常量显式转换为varchar类型,结果如下: EXPLAIN verbose SELECT * FROM t1 WHERE c1 = 10::varchar; 为了提前识别隐式类型转换可能带来的性能影响,GaussDB提供了一个guc option:check_implicit_conversions。打开该参数后,对于查询中出现的隐式类型转换的索引列,在路径生成阶段进行检查,如果发现索引列没有生成候选的索引扫描路径,则会通过报错的形式提示给用户。举例如下: SET check_implicit_conversions = on; SELECT * FROM t1 WHERE c1 = 10; ERROR: There is no optional index path for index column: "t1"."c1". 参数check_implicit_conversions只用于检查隐式类型转换引起的潜在性能问题,在正式生产环境中请关闭该参数(该参数默认关闭)。 在将check_implicit_conversions打开时,必须同时关闭enable_fast_query_shipping参数,否则由于后一个参数的作用,无法查看对隐式类型转换修复的结果。 一个表的候选路径可能包括seq scan和index scan等多个可能的数据扫描方式,最终执行计划使用的表扫描方式是由执行计划的代价来决定的,因此即使生成了索引扫描的候选路径,也可能生成的最终执行计划中使用其它扫描方式。 父主题: SQL调优指南
  • 调优手段之统计信息 GaussDB优化器是典型的基于代价的优化 (Cost-Based Optimization,简称CBO)。在这种优化器模型下,数据库根据表的元组数、字段宽度、NULL记录比率、distinct值、MCV值、HB值等表的特征值,以及一定的代价计算模型,计算出每一个执行步骤的不同执行方式的输出元组数和执行代价(cost),进而选出整体执行代价最小/首元组返回代价最小的执行方式进行执行。这些特征值就是统计信息。从上面描述可以看出统计信息是查询优化的核心输入,准确的统计信息将帮助规划器选择最合适的查询规划,一般来说通过analyze语法收集整个表或者表的若干个字段的统计信息,周期性地运行ANALYZE,或者在对表的大部分内容做了更改之后马上运行它是个好习惯。 注意,DDL可能会导致统计信息发生变化,进而导致计划跳变。当表上做了DDL操作后,应注意统计信息是否需要重新收集。
  • 调优手段之GUC参数 查询优化的主要目的是为查询语句选择高效的执行方式。 如下SQL语句: 1 2 select count(1) from customer inner join store_sales on (ss_customer_sk = c_customer_sk); 在执行customer inner join store_sales的时候,GaussDB支持Nested Loop、Merge Join和Hash Join三种不同的Join方式。优化器会根据表customer和表store_sales的统计信息估算结果集的大小以及每种Join方式的执行代价,然后对比选出执行代价最小的执行计划。 正如前面所说,执行代价计算都是基于一定的模型和统计信息进行估算,当因为某些原因代价估算不能反映真实的cost的时候,就需要通过GUC参数设置的方式让执行计划倾向更优规划。例如:random_page_cost参数表示优化器计算一次非顺序抓取磁盘页面的开销,该参数默认值为4。当机器磁盘随机读取的速度较快时,比如SSD设备,可以将该参数的值适当调小,更改后,索引扫描的代价降低,生成计划时更倾向于选择索引扫描的方式。
  • 调优手段之统计信息 GaussDB优化器是典型的基于代价的优化(Cost-Based Optimization,简称CBO)。在这种优化器模型下,数据库根据表的元组数、字段宽度、NULL记录比率、distinct值、MCV值、HB值等表的特征值,以及一定的代价计算模型,计算出每一个执行步骤的不同执行方式的输出元组数和执行代价(cost),进而选出整体执行代价最小/首元组返回代价最小的执行方式进行执行。这些特征值就是统计信息。从上面描述可以看出统计信息是查询优化的核心输入,准确的统计信息将帮助优化器选择最合适的查询规划,一般来说通过ANALYZE语法收集整个表或者表的若干个字段的统计信息,周期性地运行ANALYZE,或者在对表的大部分内容做了更改之后马上运行它是个好习惯。 注意,DDL可能会导致统计信息发生变化,进而导致计划跳变。当表上做了DDL操作后,应注意统计信息是否需要重新收集。
  • 调优手段之GUC参数 查询优化的主要目的是为查询语句选择高效的执行方式。 如下SQL语句: 1 2 select count(1) from customer inner join store_sales on (ss_customer_sk = c_customer_sk); 在执行customer inner join store_sales的时候,GaussDB支持Nested Loop、Merge Join和Hash Join三种不同的Join方式。优化器会根据表customer和表store_sales的统计信息估算结果集的大小以及每种Join方式的执行代价,然后对比选出执行代价最小的执行计划。 正如前面所说,执行代价计算都是基于一定的模型和统计信息进行估算,当因为某些原因代价估算不能反映真实的cost的时候,就需要通过GUC参数设置的方式让执行计划倾向更优规划。例如:random_page_cost参数表示优化器计算一次非顺序抓取磁盘页面的开销,该参数默认值为4。当机器磁盘随机读取的速度较快时,比如SSD设备,可以将该参数的值适当调小,更改后,索引扫描的代价降低,生成计划时更倾向于选择索引扫描的方式。
  • 调优手段之统计信息 GaussDB优化器是典型的基于代价的优化(Cost-Based Optimization,简称CBO)。在这种优化器模型下,数据库根据表的元组数、字段宽度、NULL记录比率、distinct值、MCV值、HB值等表的特征值,以及一定的代价计算模型,计算出每一个执行步骤的不同执行方式的输出元组数和执行代价(cost),进而选出整体执行代价最小/首元组返回代价最小的执行方式进行执行。这些特征值就是统计信息。从上面描述可以看出统计信息是查询优化的核心输入,准确的统计信息将帮助优化器选择最合适的查询规划,一般来说通过ANALYZE语法收集整个表或者表的若干个字段的统计信息,周期性地运行ANALYZE,或者在对表的大部分内容做了更改之后马上运行它是个好习惯。 注意,DDL可能会导致统计信息发生变化,进而导致计划跳变。当表上做了DDL操作后,应注意统计信息是否需要重新收集。