LoginSignup
6
5

More than 5 years have passed since last update.

単純なINSERT文でもバインド変数のサイズの違いで複数の子カーソルが生成される(Oracle Database)

Last updated at Posted at 2017-09-03

表題の通り、やってみるやで彡(゚)(゚)

INSERTするバインド変数の大きさの順番/組み合わせで挙動が変わるので、
まずはバイト数が小さい順にINSERTしてみるやで。

バイト数の小さい順にINSERT

実行するSQLは下記

-- 共有プールをFLUSH
ALTER SYSTEM FLUSH SHARED_POOL;

-- テーブル作成
DROP TABLE TBL_A PURGE;
CREATE TABLE TBL_A(C1 VARCHAR2(4000));

-- 1バイトのバインド変数でINSERT
VAR B1 VARCHAR2(1);
EXEC :B1 := 'A';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- 40バイトのバインド変数でINSERT
VAR B1 VARCHAR2(40);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- 200バイトのバインド変数でINSERT
VAR B1 VARCHAR2(200);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- V$SQLで子カーソルを確認
SET LINESIZE 300;
SET PAGESIZE 100;
COLUMN SQL_TEXT FORMAT A60;
SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
WHERE SQL_ID = 'g47kmy54uf3nm';

-- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
COLUMN BIND_NAME FORMAT A30;
SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = 'g47kmy54uf3nm');

-- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = 'g47kmy54uf3nm';

結果は以下の通り


SQL> -- V$SQLで子カーソルを確認
SQL> SET LINESIZE 300;
SQL> SET PAGESIZE 100;
SQL> COLUMN SQL_TEXT FORMAT A60;
SQL> SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
  2  WHERE SQL_ID = 'g47kmy54uf3nm';

SQL_ID        CHILD_NUMBER PLAN_HASH_VALUE CHILD_ADDRESS    SQL_TEXT
------------- ------------ --------------- ---------------- -----------------------------
g47kmy54uf3nm            0               0 000000006C45E450 INSERT INTO TBL_A VALUES(:B1) 1つ目の子カーソル
g47kmy54uf3nm            1               0 000000006CD519E0 INSERT INTO TBL_A VALUES(:B1) 2つ目の子カーソル
g47kmy54uf3nm            2               0 000000006ECC0660 INSERT INTO TBL_A VALUES(:B1) 3つ目の子カーソル

SQL> -- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
SQL> COLUMN BIND_NAME FORMAT A30;
SQL> SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
  2  WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = 'g47kmy54uf3nm');

ADDRESS            POSITION   DATATYPE MAX_LENGTH BIND_NAME
---------------- ---------- ---------- ---------- ---------
000000006C45E450          1          1         32 B1        ★バインド変数のMAX_LENGTH値が  32バイト
000000006CD519E0          1          1        128 B1        ★バインド変数のMAX_LENGTH値が 128バイト
000000006ECC0660          1          1       2000 B1        ★バインド変数のMAX_LENGTH値が2000バイト

SQL> -- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SQL> SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
  2  FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = 'g47kmy54uf3nm';

SQL_ID        CHILD_ADDRESS    CHILD_NUMBER H B
------------- ---------------- ------------ - -
g47kmy54uf3nm 000000006C45E450            0 N N
g47kmy54uf3nm 000000006CD519E0            1 Y Y HASH_MATCH_FAILED  BIND_LENGTH_UPGRADEABLE列が N
g47kmy54uf3nm 000000006ECC0660            2 Y Y HASH_MATCH_FAILED  BIND_LENGTH_UPGRADEABLE列が N

バイト数の大きい順にINSERT

実行するSQLは下記

-- 共有プールをFLUSH
ALTER SYSTEM FLUSH SHARED_POOL;

-- テーブル作成
DROP TABLE TBL_A PURGE;
CREATE TABLE TBL_A(C1 VARCHAR2(4000));

-- 200バイトのバインド変数でINSERT
VAR B1 VARCHAR2(200);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- 40バイトのバインド変数でINSERT
VAR B1 VARCHAR2(40);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- 1バイトのバインド変数でINSERT
VAR B1 VARCHAR2(1);
EXEC :B1 := 'A';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_A VALUES(:B1);
COMMIT;

-- V$SQLで子カーソルを確認
SET LINESIZE 300;
SET PAGESIZE 100;
COLUMN SQL_TEXT FORMAT A60;
SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
WHERE SQL_ID = 'g47kmy54uf3nm';

-- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
COLUMN BIND_NAME FORMAT A30;
SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = 'g47kmy54uf3nm');

-- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = 'g47kmy54uf3nm';

結果は以下の通りで、子カーソルは1つだけなんですやね彡(゚)(゚)

SQL> -- V$SQLで子カーソルを確認
SQL> SET LINESIZE 300;
SQL> SET PAGESIZE 100;
SQL> COLUMN SQL_TEXT FORMAT A60;
SQL> SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
  2  WHERE SQL_ID = 'g47kmy54uf3nm';

SQL_ID        CHILD_NUMBER PLAN_HASH_VALUE CHILD_ADDRESS    SQL_TEXT
------------- ------------ --------------- ---------------- -----------------------------
g47kmy54uf3nm            0               0 000000006EE9F7B8 INSERT INTO TBL_A VALUES(:B1) ★子カーソルは1つだけ

SQL>
SQL> -- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
SQL> COLUMN BIND_NAME FORMAT A30;
SQL> SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
  2  WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = 'g47kmy54uf3nm');

ADDRESS            POSITION   DATATYPE MAX_LENGTH BIND_NAME
---------------- ---------- ---------- ---------- ---------
000000006EE9F7B8          1          1       2000 B1       ★バインド変数のMAX_LENGTH値が2000バイト

SQL>
SQL> -- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SQL> SELECT * FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = 'g47kmy54uf3nm';

SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER U S O O S L F E B P I S T A B D L T B I I R L I O E M U T N F A P T D L D B P C S C P T M B M R O P M F L P L A F L R L H P B U REASON                                                                             CON_ID
------------- ---------------- ---------------- ------------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -------------------------------------------------------------------------------- ----------
g47kmy54uf3nm 0000000070E32AF8 000000006EE9F7B8            0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N                                                                                         0

SQL> SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
  2  FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = 'g47kmy54uf3nm';

SQL_ID        CHILD_ADDRESS    CHILD_NUMBER H B
------------- ---------------- ------------ - -
g47kmy54uf3nm 000000006EE9F7B8            0 N N

複数バインド変数の組み合わせで小さい順にINSERT

複数バインド変数の場合は、それぞれのバインド変数の組み合わせでも
子カーソルが生成されます。以下のSQLを実行してみます。

-- 共有プールをFLUSH
ALTER SYSTEM FLUSH SHARED_POOL;

-- テーブル作成
DROP TABLE TBL_B PURGE;
CREATE TABLE TBL_B(
    C1 VARCHAR2(4000)
  , C2 VARCHAR2(4000)
);

-- 1バイトのバインド変数*2でINSERT
VAR B1 VARCHAR2(1);
VAR B2 VARCHAR2(1);
EXEC :B1 := 'A';
EXEC :B2 := 'B';
-- sql_id = '5f5u0gky3kjpc'
INSERT INTO TBL_B VALUES(:B1, :B2);
COMMIT;

-- 1バイト&40バイトのバインド変数でINSERT
VAR B1 VARCHAR2(1);
VAR B2 VARCHAR2(40);
EXEC :B1 := 'A';
EXEC :B2 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = '5f5u0gky3kjpc'
INSERT INTO TBL_B VALUES(:B1, :B2);
COMMIT;

-- 40バイト&1バイトのバインド変数でINSERT
VAR B1 VARCHAR2(40);
VAR B2 VARCHAR2(1);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
EXEC :B2 := 'A';
-- sql_id = '5f5u0gky3kjpc'
INSERT INTO TBL_B VALUES(:B1, :B2);
COMMIT;

-- 40バイトのバインド変数*2でINSERT
VAR B1 VARCHAR2(40);
VAR B2 VARCHAR2(40);
EXEC :B1 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
EXEC :B2 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
-- sql_id = 'g47kmy54uf3nm'
INSERT INTO TBL_B VALUES(:B1, :B2);
COMMIT;

-- V$SQLで子カーソルを確認
SET LINESIZE 300;
SET PAGESIZE 100;
COLUMN SQL_TEXT FORMAT A60;
SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
WHERE SQL_ID = '5f5u0gky3kjpc';

-- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
COLUMN BIND_NAME FORMAT A30;
SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = '5f5u0gky3kjpc')
ORDER BY ADDRESS, POSITION;

-- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = '5f5u0gky3kjpc';

結果は以下の通りで、複数の子カーソルが生成されるんやで彡(゚)(゚)

SQL> -- V$SQLで子カーソルを確認
SQL> SET LINESIZE 300;
SQL> SET PAGESIZE 100;
SQL> COLUMN SQL_TEXT FORMAT A60;
SQL> SELECT SQL_ID, CHILD_NUMBER, PLAN_HASH_VALUE, CHILD_ADDRESS, SQL_TEXT FROM V$SQL
  2  WHERE SQL_ID = '5f5u0gky3kjpc';

SQL_ID        CHILD_NUMBER PLAN_HASH_VALUE CHILD_ADDRESS    SQL_TEXT
------------- ------------ --------------- ---------------- ----------------------------------
5f5u0gky3kjpc            0               0 000000006EB29608 INSERT INTO TBL_B VALUES(:B1, :B2) 1つ目の子カーソル
5f5u0gky3kjpc            1               0 000000006C94E5C0 INSERT INTO TBL_B VALUES(:B1, :B2) 2つ目の子カーソル
5f5u0gky3kjpc            2               0 000000006E6F3638 INSERT INTO TBL_B VALUES(:B1, :B2) 3つ目の子カーソル

SQL>
SQL> -- V$SQL_BIND_METADATAで子カーソルのバインド変数を確認
SQL> COLUMN BIND_NAME FORMAT A30;
SQL> SELECT ADDRESS, POSITION, DATATYPE, MAX_LENGTH, BIND_NAME FROM V$SQL_BIND_METADATA
  2  WHERE ADDRESS IN (SELECT CHILD_ADDRESS FROM V$SQL WHERE SQL_ID = '5f5u0gky3kjpc')
  3  ORDER BY ADDRESS, POSITION;

ADDRESS            POSITION   DATATYPE MAX_LENGTH BIND_NAME
---------------- ---------- ---------- ---------- ---------
000000006C94E5C0          1          1         32 B1 2つ目の子カーソルのバインド変数定義
000000006C94E5C0          2          1        128 B2 2つ目の子カーソルのバインド変数定義
000000006E6F3638          1          1        128 B1 3つ目の子カーソルのバインド変数定義
000000006E6F3638          2          1        128 B2 3つ目の子カーソルのバインド変数定義
000000006EB29608          1          1         32 B1 1つ目の子カーソルのバインド変数定義
000000006EB29608          2          1         32 B2 1つ目の子カーソルのバインド変数定義

6 rows selected.

SQL>
SQL> -- V$SQL_SHARED_CURSORで子カーソルの生成理由を確認
SQL> SELECT SQL_ID, CHILD_ADDRESS, CHILD_NUMBER, HASH_MATCH_FAILED, BIND_LENGTH_UPGRADEABLE
  2  FROM V$SQL_SHARED_CURSOR WHERE SQL_ID = '5f5u0gky3kjpc';

SQL_ID        CHILD_ADDRESS    CHILD_NUMBER H B
------------- ---------------- ------------ - -
5f5u0gky3kjpc 000000006EB29608            0 N N
5f5u0gky3kjpc 000000006C94E5C0            1 Y Y
5f5u0gky3kjpc 000000006E6F3638            2 Y Y

という訳で単純なINSERT文でも複数の子カーソルが生成されることを確認できました。

参考資料(マニュアル)

マニュアルも見とくんやで!彡(^)(^)

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5