本文介绍Access Method Hints。
语法
以下hints影响优化器如何访问关系以创建结果集。
提示 | 说明 |
FULL(table) | 对table执行完整顺序扫描。 |
INDEX(table [ index ] [...]) | 使用table中的index访问关系。 |
NO_INDEX(table [ index ] [...]) | 不使用table中的index访问关系。 |
此外,可以使用默认优化模式的 ALL_ROWS、FIRST_ROWS 和 FIRST_ROWS(n) 提示。
示例
准备基础数据。示例应用程序没有足够的数据来说明optimizer hints的效果,因此本节中的其余示例将使用压力测试工具pgbench应用程序创建的bank数据库。
创建一个Linux操作系统的ECS实例,本案例使用的ECS为CentOS 7.6 64位操作系统。详情请参考自定义购买ECS实例。
说明建议ECS实例和PolarDB集群在同一可用区和VPC。
在ECS实例中安装PostgreSQL客户端,详情请参考PostgreSQL官方文档。
说明请确保安装的PostgreSQL客户端版本与连接的PolarDB PostgreSQL版(兼容Oracle)集群版本兼容。
创建高权限账户,详细操作请参考创建账号。
获取集群地址,详细操作请参考查看连接地址。
如果PolarDB集群和ECS在同一可用区,可直接使用私网地址,否则需要申请公网地址。将ECS实例的地址添加到PolarDB集群白名单中,请参考设置集群白名单。
在控制台创建测试数据库bank,详细步骤请参考创建数据库。
在ECS客户端执行如下语句,为bank数据库填充pgbench_accounts、pgbench_branches、pgbench_tellers和pgbench_history表。
pgbench -h <PolarDB集群地址> -p <PolarDB集群地址的端口> -i -s 20 -U <PolarDB数据库用户名> bank
其中,–s选项指定的比例因子为20,创建20个分行,每个具有100,000个账户,在pgbench_accounts表中生成2,000,000行并在pgbench_branches表中生成20行。每个分行分配10个出纳员,从而在pgbench_tellers表中总计生成200行。
然后处理总计500,000次交易,为pgbench_history表填充500,000行。
pgbench -h <PolarDB集群地址> -p <PolarDB集群地址的端口> -t 500000 -U <PolarDB数据库用户名> bank
以下使用psql查询表结构,您也可以使用其他工具查询,使用DMS查询请参考查询表结构。
\d pgbench_accounts Table "public.pgbench_accounts" Column | Type | Modifiers ----------+---------------+----------- aid | integer | not null bid | integer | abalance | integer | filler | character(84) | Indexes: "pgbench_accounts_pkey" PRIMARY KEY, btree (aid) \d pgbench_branches Table "public.pgbench_branches" Column | Type | Modifiers ----------+---------------+----------- bid | integer | not null bbalance | integer | filler | character(88) | Indexes: "pgbench_branches_pkey" PRIMARY KEY, btree (bid) \d pgbench_tellers Table "public.pgbench_tellers" Column | Type | Modifiers ----------+---------------+----------- tid | integer | not null bid | integer | tbalance | integer | filler | character(84) | Indexes: "pgbench_tellers_pkey" PRIMARY KEY, btree (tid) \d pgbench_history Table "public.pgbench_history" Column | Type | Modifiers --------+-----------------------------+----------- tid | integer | bid | integer | aid | integer | delta | integer | mtime | timestamp without time zone | filler | character(22) |
执行如下查询。
使用EXPLAIN命令显示查询计划程序选择的计划。在以下示例中,aid是主键列,因此对索引 pgbench_accounts_pkey使用编索引的搜索。
EXPLAIN SELECT * FROM pgbench_accounts WHERE aid = 100;
返回结果如下:
QUERY PLAN ----------------------------------------------------------------------------------------------- Index Scan using pgbench_accounts_pkey on pgbench_accounts (cost=0.43..8.45 rows=1 width=97) Index Cond: (aid = 100) (2 rows)
FULL hint用于强制执行完整顺序扫描,而不是使用索引,如下所示:
EXPLAIN SELECT /*+ FULL(pgbench_accounts) */ * FROM pgbench_accounts WHERE aid = 100;
返回结果如下:
QUERY PLAN --------------------------------------------------------------------- Seq Scan on pgbench_accounts (cost=0.00..58781.69 rows=1 width=97) Filter: (aid = 100) (2 rows)
NO_INDEX hint强制执行并行顺序扫描,而不是使用索引,如下所示:
EXPLAIN SELECT /*+ NO_INDEX(pgbench_accounts pgbench_accounts_pkey) */ * FROM pgbench_accounts WHERE aid = 100;
返回结果如下:
QUERY PLAN ------------------------------------------------------------------------------------ Gather (cost=1000.00..45094.80 rows=1 width=97) Workers Planned: 2 -> Parallel Seq Scan on pgbench_accounts (cost=0.00..44094.70 rows=1 width=97) Filter: (aid = 100) (4 rows)
除了如之前示例中所示使用EXPLAIN命令以外,还可通过设置trace_hints配置参数获得有关计划程序是否使用提示的更详细信息,如下所示:
SET trace_hints TO on;
下面重复带NO_INDEX hint的SELECT命令,以说明设置trace_hints配置参数后生成的其他信息。
EXPLAIN SELECT /*+ NO_INDEX(pgbench_accounts pgbench_accounts_pkey) */ * FROM pgbench_accounts WHERE aid = 100;
返回结果如下:
INFO: [HINTS] Index Scan of [pgbench_accounts].[pgbench_accounts_pkey] rejected due to NO_INDEX hint. QUERY PLAN ------------------------------------------------------------------------------------ Gather (cost=1000.00..45094.80 rows=1 width=97) Workers Planned: 2 -> Parallel Seq Scan on pgbench_accounts (cost=0.00..44094.70 rows=1 width=97) Filter: (aid = 100) (4 rows)
请注意,如果忽略hint,则
INFO: [HINTS]
行将不会显示。这可能表示hint中存在语法错误或一些其他拼写错误,如以下示例中所示,其中索引名称拼写错误。EXPLAIN SELECT /*+ NO_INDEX(pgbench_accounts pgbench_accounts_xxx) */ * FROM pgbench_accounts WHERE aid = 100;
返回结果如下:
QUERY PLAN ----------------------------------------------------------------------------------------------- Index Scan using pgbench_accounts_pkey on pgbench_accounts (cost=0.43..8.45 rows=1 width=97) Index Cond: (aid = 100) (2 rows)