在ORACLE中,SQL Profile 是对 SQL 语句文本的数据库级匹配。由于相同的 SQL 文本在不同用户下可能会受到影响,因此需要一些方法来避免这种情况。OceanBase 提供了 outline 功能,可以用于固定执行计划。那么在 OceanBase 中是否存在与 ORACLE 类似的、影响不同用户的问题呢?多个用户的相同 SQL 语句和相同的表是否共享同一个 outline 呢?outline 是全库共享的还是用户级私有的?
Oracle 、Oceanbase、GoldenDB数据库比较系列(二十四):sql profile/ outline 影响范围(上)
Oracle 、Oceanbase、GoldenDB数据库比较系列(二十五):sql profile/ outline 影响范围(中)
–测试Oceanbase V4.2.1 for oracle租户
初始化数据
--首先同一个租户创建两个用户anbob, weejar,省略
obclient [SYS]> grant dba to weejar,anbob;
Query OK, 0 rows affected (1.183 sec)
SQL> create table weejar.test_profile(id int,name varchar2(100));
Table created.
SQL> create table anbob.test_profile(id int,name varchar2(100));
Table created.
obclient [SYS]> insert into anbob.test_profile select 1,'weejar'||rownum from dual connect by rownum<=10000;
Query OK, 10000 rows affected (2.516 sec)
Records: 10000 Duplicates: 0 Warnings: 0
obclient [SYS]> insert into weejar.test_profile select rownum,'weejar'||rownum from xmltable('1 to 10000');
ORA-00600: internal error code, arguments: -5055, FUNCTION XMLTABLE does not exist --- No supported XMLTABLE
obclient [SYS]> insert into weejar.test_profile select rownum,'weejar'||rownum from dual connect by rownum<=10000;
Query OK, 10000 rows affected (1.950 sec)
Records: 10000 Duplicates: 0 Warnings: 0
obclient [SYS]> create index anbob.idx_test_profile on anbob.test_profile(id);
Query OK, 0 rows affected (28.000 sec)
obclient [SYS]> create index weejar.idx_test_profile on weejar.test_profile(id);
Query OK, 0 rows affected (31.503 sec)
Note:
和上篇测试一样,两个用户,分别创建一个相同的表,数据不同的选择率,用于full table scan 和index scan。
验证执行计划
--- # weejar user
[root@localhost 4.2.3]# obclient -h192.168.56.100 -P2883 -uweejar@ob_ora -pweejar
Welcome to the OceanBase. Commands end with ; or \g.
Your OceanBase connection id is 524289
Server version: OceanBase 4.2.1.2 (r102010012023120119-130bf91ba413a00bb696fe8853906fde1f29f83d) (Built Dec 1 2023 20:00:25)
Copyright (c) 2000, 2018, OceanBase and/or its affiliates. All rights reserved.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
obclient [WEEJAR]> explain select * from test_profile where id=1;
+-----------------------------------------------------------------------------------------------------+
| Query Plan |
+-----------------------------------------------------------------------------------------------------+
| ========================================================================== |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| -------------------------------------------------------------------------- |
| |0 |TABLE RANGE SCAN|TEST_PROFILE(IDX_TEST_PROFILE)|1 |7 | |
| ========================================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([TEST_PROFILE.ID], [TEST_PROFILE.NAME]), filter(nil), rowset=16 |
| access([TEST_PROFILE.__pk_increment], [TEST_PROFILE.ID], [TEST_PROFILE.NAME]), partitions(p0) |
| is_index_back=true, is_global_index=false, |
| range_key([TEST_PROFILE.ID], [TEST_PROFILE.__pk_increment]), range(1,MIN ; 1,MAX), |
| range_cond([TEST_PROFILE.ID = 1]) |
+-----------------------------------------------------------------------------------------------------+
12 rows in set (0.485 sec)
--- # anbob user
# obclient -h192.168.56.100 -P2883 -uanbob@ob_ora -panbob
Welcome to the OceanBase. Commands end with ; or \g.
Your OceanBase connection id is 6
Server version: OceanBase 4.2.1.2 (r102010012023120119-130bf91ba413a00bb696fe8853906fde1f29f83d) (Built Dec 1 2023 20:00:25)
Copyright (c) 2000, 2018, OceanBase and/or its affiliates. All rights reserved.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
obclient [ANBOB]> explain select * from test_profile where id=1;
+-------------------------------------------------------------------------------------------------+
| Query Plan |
+-------------------------------------------------------------------------------------------------+
| ======================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ------------------------------------------------------- |
| |0 |TABLE FULL SCAN|TEST_PROFILE|10000 |420 | |
| ======================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([TEST_PROFILE.ID], [TEST_PROFILE.NAME]), filter([TEST_PROFILE.ID = 1]), rowset=256 |
| access([TEST_PROFILE.ID], [TEST_PROFILE.NAME]), partitions(p0) |
| is_index_back=false, is_global_index=false, filter_before_indexback[false], |
| range_key([TEST_PROFILE.__pk_increment]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------------------------------------+
11 rows in set (0.346 sec)
不用户相同SQL不同的表,OUTLINE共享?
在Oceanbase中创建 Outline,可以通过两种方式创建,一种是通过 SQL_TEXT(用户执行的带参数的原始语句),另一种是通过 SQL_ID 创建。 注:创建 Outline 需要进入对应的数据库下执行。,当 SQL_ID 相同时,使用 SQL_TEXT 方式创建的 Outline 会覆盖 SQL_ID 方式创建的 Outline,SQL_TEXT 方式创建的优先级更高。
# anbob
obclient [ANBOB]> select /*anbob_test*/ * from test_profile where id=1;
+------+-------------+
| ID | NAME |
+------+-------------+
| 1 | weejar1 |
| 1 | weejar2 |
| 1 | weejar3 |
...
+------+-------------+
10000 rows in set (0.264 sec)
#weejar
obclient [WEEJAR]> select /*anbob_test*/ * from test_profile where id=1;
+------+---------+
| ID | NAME |
+------+---------+
| 1 | weejar1 |
+------+---------+
1 row in set (0.562 sec)
# SYS
select tenant_id,db_id,svr_ip,svr_port,plan_id,sql_id,query_sql from GV$OB_PLAN_CACHE_PLAN_STAT where lower(query_sql) not like '%plan_cache_plan_stat%' and query_sql like '%anbob_test%';
obclient [SYS]> select tenant_id,db_id,svr_ip,svr_port,plan_id,sql_id,query_sql,SCHEMA_VERSION,EXECUTIONS,ROWS_PROCESSED,LARGE_QUERYS,OUTLINE_VERSION,OUTLINE_ID,HINTS_INFO from GV$OB_PLAN_CACHE_PLAN_STAT where lower(query_sql) not like '%plan_cache_plan_stat%' and query_sql like '%anbob_test%' \G
*************************** 1. row ***************************
TENANT_ID: 1002
DB_ID: 500003
SVR_IP: 192.168.56.100
SVR_PORT: 2882
PLAN_ID: 128
SQL_ID: 799B8543872CDA344B34E9BF5E0107E9
QUERY_SQL: select /*anbob_test*/ * from test_profile where id=1
SCHEMA_VERSION: 1721902231508616
EXECUTIONS: 1
ROWS_PROCESSED: 10000
LARGE_QUERYS: 0
OUTLINE_VERSION: 0
OUTLINE_ID: -1
HINTS_INFO: NULL
*************************** 2. row ***************************
TENANT_ID: 1002
DB_ID: 500005
SVR_IP: 192.168.56.100
SVR_PORT: 2882
PLAN_ID: 129
SQL_ID: 799B8543872CDA344B34E9BF5E0107E9
QUERY_SQL: select /*anbob_test*/ * from test_profile where id=1
SCHEMA_VERSION: 1721902231508616
EXECUTIONS: 1
ROWS_PROCESSED: 1
LARGE_QUERYS: 0
OUTLINE_VERSION: 0
OUTLINE_ID: -1
HINTS_INFO: NULL
2 rows in set (0.034 sec)
obclient [WEEJAR]> select PLAN_DEPTH,PLAN_LINE_ID,OPERATOR,NAME from gv$ob_plan_cache_plan_explain;
Empty set (0.093 sec)
obclient [SYS]> select SQL_ID,PLAN_HASH,PLAN_ID,PARENT_ID,DEPTH,OPERATOR,OBJECT_OWNER,OBJECT_NAME,OBJECT_ALIAS from V$OB_SQL_PLAN where plan_id=128;
+----------------------------------+----------------------+---------+-----------+-------+-----------------+--------------+--------------+--------------+
| SQL_ID | PLAN_HASH | PLAN_ID | PARENT_ID | DEPTH | OPERATOR | OBJECT_OWNER | OBJECT_NAME | OBJECT_ALIAS |
+----------------------------------+----------------------+---------+-----------+-------+-----------------+--------------+--------------+--------------+
| 799B8543872CDA344B34E9BF5E0107E9 | 15601764933452318478 | 128 | -1 | 0 | TABLE FULL SCAN | ANBOB | TEST_PROFILE | TEST_PROFILE |
+----------------------------------+----------------------+---------+-----------+-------+-----------------+--------------+--------------+--------------+
1 row in set (0.081 sec)
obclient [SYS]> select SQL_ID,PLAN_HASH,PLAN_ID,PARENT_ID,DEPTH,OPERATOR,OBJECT_OWNER,OBJECT_NAME,OBJECT_ALIAS from V$OB_SQL_PLAN where plan_id=129;
+----------------------------------+---------------------+---------+-----------+-------+------------------+--------------+--------------+--------------------------------+
| SQL_ID | PLAN_HASH | PLAN_ID | PARENT_ID | DEPTH | OPERATOR | OBJECT_OWNER | OBJECT_NAME | OBJECT_ALIAS |
+----------------------------------+---------------------+---------+-----------+-------+------------------+--------------+--------------+--------------------------------+
| 799B8543872CDA344B34E9BF5E0107E9 | 1212772377093033590 | 129 | -1 | 0 | TABLE RANGE SCAN | WEEJAR | TEST_PROFILE | TEST_PROFILE(IDX_TEST_PROFILE) |
+----------------------------------+---------------------+---------+-----------+-------+------------------+--------------+--------------+--------------------------------+
1 row in set (0.105 sec)
# weejar
obclient [WEEJAR]> create or replace outline outl_799B8543872CDA344B34E9BF5E0107E9 on '799B8543872CDA344B34E9BF5E0107E9' using hint /*+index(TEST_PROFILE IDX_TEST_PROFILE) */;
Query OK, 0 rows affected (2.677 sec)
# weejar
obclient [WEEJAR]> select /*anbob_test*/ * from test_profile where id=1;
+------+---------+
| ID | NAME |
+------+---------+
| 1 | weejar1 |
+------+---------+
1 row in set (0.101 sec)
# anbob
obclient [ANBOB]> select /*anbob_test*/ * from test_profile where id=1;
+------+-------------+
| ID | NAME |
+------+-------------+
| 1 | weejar1 |
| 1 | weejar2 |
| 1 | weejar3 |
...
# SYS
obclient [SYS]> select tenant_id,db_id,svr_ip,svr_port,plan_id,sql_id,query_sql,SCHEMA_VERSION,EXECUTIONS,ROWS_PROCESSED,LARGE_QUERYS,OUTLINE_VERSION,OUTLINE_ID,HINTS_INFO from GV$OB_PLAN_CACHE_PLAN_STAT where lower(query_sql) not like '%plan_cache_plan_stat%' and query_sql like '%anbob_test%' \G
*************************** 1. row ***************************
TENANT_ID: 1002
DB_ID: 500003
SVR_IP: 192.168.56.100
SVR_PORT: 2882
PLAN_ID: 128
SQL_ID: 799B8543872CDA344B34E9BF5E0107E9
QUERY_SQL: select /*anbob_test*/ * from test_profile where id=1
SCHEMA_VERSION: 1721902231508616
EXECUTIONS: 2
ROWS_PROCESSED: 20000
LARGE_QUERYS: 0
OUTLINE_VERSION: 0
OUTLINE_ID: -1
HINTS_INFO: NULL
*************************** 2. row ***************************
TENANT_ID: 1002
DB_ID: 500005
SVR_IP: 192.168.56.100
SVR_PORT: 2882
PLAN_ID: 164
SQL_ID: 799B8543872CDA344B34E9BF5E0107E9
QUERY_SQL: select /*anbob_test*/ * from test_profile where id=1
SCHEMA_VERSION: 1722761417822032
EXECUTIONS: 1
ROWS_PROCESSED: 1
LARGE_QUERYS: 0
OUTLINE_VERSION: 1722761417482704
OUTLINE_ID: 500010
HINTS_INFO: NULL
2 rows in set (0.106 sec)
obclient [SYS]> select * from dict where table_name like '%OUTLINE%';
+-----------------------------------+----------+
| TABLE_NAME | COMMENTS |
+-----------------------------------+----------+
| DBA_OB_OUTLINE_CONCURRENT_HISTORY | NULL |
| DBA_OB_OUTLINES | NULL |
+-----------------------------------+----------+
2 rows in set (0.058 sec)
obclient [SYS]> SELECT * FROM DBA_OB_OUTLINES \G
*************************** 1. row ***************************
CREATE_TIME: 04-AUG-24 04.50.17.490412 PM
MODIFY_TIME: 04-AUG-24 04.50.17.490412 PM
TENANT_ID: 1002
DATABASE_ID: 500005
OUTLINE_ID: 500010
DATABASE_NAME: WEEJAR
OUTLINE_NAME: OUTL_799B8543872CDA344B34E9BF5E0107E9
VISIBLE_SIGNATURE:
SQL_TEXT:
OUTLINE_TARGET:
OUTLINE_SQL:
SQL_ID: 799B8543872CDA344B34E9BF5E0107E9
OUTLINE_CONTENT: /*+index(TEST_PROFILE IDX_TEST_PROFILE) */
Note:
该视图从 V4.0.0 版本开始视图名由 GV$PLAN_CACHE_PLAN_STAT 调整为 GV$OB_PLAN_CACHE_PLAN_STAT。GV$PLAN_CACHE_PLAN_EXPLAIN 调整为 GV$OB_PLAN_CACHE_PLAN_EXPLAIN.
在FOR oracle租户中,虽然Oceanbase也可以像oracle中1个数据库对应多个schema(user),但是低层仍旧是MySQL式的模式,schema就是database. 所以weejar 用户创建的outline属于WEEJAR database,未影响anbob 用户。 如果是2个用户查询相同用户的表呢?outline会不会共享?
不用户相同SQL相同的表,OUTLINE共享?
# weejar
select /*anbob_full*/ * from weejar.test_profile where id=1;
# anbob
select /*anbob_full*/ * from weejar.test_profile where id=1;
# sys
obclient [SYS]> select tenant_id,db_id,svr_ip,svr_port,plan_id,sql_id,query_sql,SCHEMA_VERSION,EXECUTIONS,ROWS_PROCESSED,LARGE_QUERYS,OUTLINE_VERSION,OUTLINE_ID,HINTS_INFO from GV$OB_PLAN_CACHE_PLAN_STAT where lower(query_sql) not like '%plan_cache_plan_stat%' and query_sql like '%anbob_full%' \G
*************************** 1. row ***************************
TENANT_ID: 1002
DB_ID: 500003
SVR_IP: 192.168.56.100
SVR_PORT: 2882
PLAN_ID: 176
SQL_ID: 6DAA6297703A54EC92D35E71924B9E51
QUERY_SQL: select /*anbob_full*/ * from weejar.test_profile where id=1
SCHEMA_VERSION: 1722761417822032
EXECUTIONS: 1
ROWS_PROCESSED: 1
LARGE_QUERYS: 0
OUTLINE_VERSION: 0
OUTLINE_ID: -1
HINTS_INFO: NULL
*************************** 2. row ***************************
TENANT_ID: 1002
DB_ID: 500005
SVR_IP: 192.168.56.100
SVR_PORT: 2882
PLAN_ID: 177
SQL_ID: 6DAA6297703A54EC92D35E71924B9E51
QUERY_SQL: select /*anbob_full*/ * from weejar.test_profile where id=1
SCHEMA_VERSION: 1722761417822032
EXECUTIONS: 1
ROWS_PROCESSED: 1
LARGE_QUERYS: 0
OUTLINE_VERSION: 0
OUTLINE_ID: -1
HINTS_INFO: NULL
2 rows in set (0.151 sec)
obclient [WEEJAR]> select SQL_ID,PLAN_HASH,PLAN_ID,PARENT_ID,DEPTH,OPERATOR,OBJECT_OWNER,OBJECT_NAME,OBJECT_ALIAS from V$OB_SQL_PLAN where plan_id=176;
+----------------------------------+---------------------+---------+-----------+-------+------------------+--------------+--------------+--------------------------------+
| SQL_ID | PLAN_HASH | PLAN_ID | PARENT_ID | DEPTH | OPERATOR | OBJECT_OWNER | OBJECT_NAME | OBJECT_ALIAS |
+----------------------------------+---------------------+---------+-----------+-------+------------------+--------------+--------------+--------------------------------+
| 6DAA6297703A54EC92D35E71924B9E51 | 1212772377093033590 | 176 | -1 | 0 | TABLE RANGE SCAN | WEEJAR | TEST_PROFILE | TEST_PROFILE(IDX_TEST_PROFILE) |
+----------------------------------+---------------------+---------+-----------+-------+------------------+--------------+--------------+--------------------------------+
1 row in set (0.100 sec)
obclient [WEEJAR]> select SQL_ID,PLAN_HASH,PLAN_ID,PARENT_ID,DEPTH,OPERATOR,OBJECT_OWNER,OBJECT_NAME,OBJECT_ALIAS from V$OB_SQL_PLAN where plan_id=177;
+----------------------------------+---------------------+---------+-----------+-------+------------------+--------------+--------------+--------------------------------+
| SQL_ID | PLAN_HASH | PLAN_ID | PARENT_ID | DEPTH | OPERATOR | OBJECT_OWNER | OBJECT_NAME | OBJECT_ALIAS |
+----------------------------------+---------------------+---------+-----------+-------+------------------+--------------+--------------+--------------------------------+
| 6DAA6297703A54EC92D35E71924B9E51 | 1212772377093033590 | 177 | -1 | 0 | TABLE RANGE SCAN | WEEJAR | TEST_PROFILE | TEST_PROFILE(IDX_TEST_PROFILE) |
+----------------------------------+---------------------+---------+-----------+-------+------------------+--------------+--------------+--------------------------------+
1 row in set (0.078 sec)
obclient [WEEJAR]> create or replace outline outl_6DAA6297703A54EC92D35E71924B9E51 on '6DAA6297703A54EC92D35E71924B9E51' using hint /*+FULL(TEST_PROFILE) */;
Query OK, 0 rows affected (0.146 sec)
# anbob
obclient [ANBOB]> select /*anbob_full*/ * from weejar.test_profile where id=1;
+------+---------+
| ID | NAME |
+------+---------+
| 1 | weejar1 |
+------+---------+
1 row in set (0.014 sec)
# weejar
obclient [WEEJAR]> select /*anbob_full*/ * from weejar.test_profile where id=1;
+------+---------+
| ID | NAME |
+------+---------+
| 1 | weejar1 |
+------+---------+
1 row in set (0.336 sec)
obclient [WEEJAR]> select tenant_id,db_id,svr_ip,svr_port,plan_id,sql_id,query_sql,SCHEMA_VERSION,EXECUTIONS,ROWS_PROCESSED,LARGE_QUERYS,OUTLINE_VERSION,OUTLINE_ID,HINTS_INFO from GV$OB_PLAN_CACHE_PLAN_STAT where lower(query_sql) not like '%plan_cache_plan_stat%' and query_sql like '%anbob_full%' \G
*************************** 1. row ***************************
TENANT_ID: 1002
DB_ID: 500003
SVR_IP: 192.168.56.100
SVR_PORT: 2882
PLAN_ID: 176
SQL_ID: 6DAA6297703A54EC92D35E71924B9E51
QUERY_SQL: select /*anbob_full*/ * from weejar.test_profile where id=1
SCHEMA_VERSION: 1722761417822032
EXECUTIONS: 1
ROWS_PROCESSED: 1
LARGE_QUERYS: 0
OUTLINE_VERSION: 0
OUTLINE_ID: -1
HINTS_INFO: NULL
*************************** 2. row ***************************
TENANT_ID: 1002
DB_ID: 500005
SVR_IP: 192.168.56.100
SVR_PORT: 2882
PLAN_ID: 180
SQL_ID: 6DAA6297703A54EC92D35E71924B9E51
QUERY_SQL: select /*anbob_full*/ * from weejar.test_profile where id=1
SCHEMA_VERSION: 1722762253742432
EXECUTIONS: 1
ROWS_PROCESSED: 1
LARGE_QUERYS: 0
OUTLINE_VERSION: 1722762253741024
OUTLINE_ID: 500011
HINTS_INFO: NULL
2 rows in set (0.093 sec)
obclient [WEEJAR]> select SQL_ID,PLAN_HASH,PLAN_ID,PARENT_ID,DEPTH,OPERATOR,OBJECT_OWNER,OBJECT_NAME,OBJECT_ALIAS from V$OB_SQL_PLAN where plan_id=180;
+----------------------------------+----------------------+---------+-----------+-------+-----------------+--------------+--------------+--------------+
| SQL_ID | PLAN_HASH | PLAN_ID | PARENT_ID | DEPTH | OPERATOR | OBJECT_OWNER | OBJECT_NAME | OBJECT_ALIAS |
+----------------------------------+----------------------+---------+-----------+-------+-----------------+--------------+--------------+--------------+
| 6DAA6297703A54EC92D35E71924B9E51 | 15601764933452318478 | 180 | -1 | 0 | TABLE FULL SCAN | WEEJAR | TEST_PROFILE | TEST_PROFILE |
+----------------------------------+----------------------+---------+-----------+-------+-----------------+--------------+--------------+--------------+
1 row in set (0.026 sec)
obclient [SYS]> SELECT * FROM DBA_OB_OUTLINES \G
*************************** 1. row ***************************
CREATE_TIME: 04-AUG-24 04.50.17.490412 PM
MODIFY_TIME: 04-AUG-24 04.50.17.490412 PM
TENANT_ID: 1002
DATABASE_ID: 500005
OUTLINE_ID: 500010
DATABASE_NAME: WEEJAR
OUTLINE_NAME: OUTL_799B8543872CDA344B34E9BF5E0107E9
VISIBLE_SIGNATURE:
SQL_TEXT:
OUTLINE_TARGET:
OUTLINE_SQL:
SQL_ID: 799B8543872CDA344B34E9BF5E0107E9
OUTLINE_CONTENT: /*+index(TEST_PROFILE IDX_TEST_PROFILE) */
*************************** 2. row ***************************
CREATE_TIME: 04-AUG-24 05.04.13.710763 PM
MODIFY_TIME: 04-AUG-24 05.04.13.710763 PM
TENANT_ID: 1002
DATABASE_ID: 500005
OUTLINE_ID: 500011
DATABASE_NAME: WEEJAR
OUTLINE_NAME: OUTL_6DAA6297703A54EC92D35E71924B9E51
VISIBLE_SIGNATURE:
SQL_TEXT:
OUTLINE_TARGET:
OUTLINE_SQL:
SQL_ID: 6DAA6297703A54EC92D35E71924B9E51
OUTLINE_CONTENT: /*+FULL(TEST_PROFILE) */
2 rows in set (0.064 sec)
Note:
相同表相同的SQL,只是SCHEMA_VERSION相同,但是一样不会共享outline.
小结:
在oceanbase中outline是用户私有的,不像oracle中的共享(默认)SQL PROFILE,这可能是基于不同的设计。只是默认情况,Oceanbase中这种减少了互相影响,也不用像oracle中配置session 变量限制,从现实中的应用设计维度,这点个人感觉OB比Orale更佳。
多个用户多个table(含索引)相同结构,对于相同的SQL文本,是否会互相影响?
不会!
多个用户相同的table, 对于相同的SQL文本,是否会互相影响?
不会!