Title |
[ORACLE] BITMAP CONVERSIONによるWRONG RESULT | Product |
Plug-In |
---|---|---|---|
Phenomenon |
暗号化前に1rowをreturnしていたqueryが、暗号化後には0rowをreturnする。
暗号化前の原本SQL SQL> select a.事業者登録番号、a.代表者名、a.個人番号、b.個人識別番号、a.代表者電子メール 2 from 使用_業者代表者詳細 a, 使用_個人情報 b 3 where a.事業者登録番号 = '1234567890' 4 and a.個人番号 = b.個人番号 5 and b.識別区分コード='1' 6 and b.個人識別番号like '8%' 7 order by代表者名 8 ; Execution Plan ---------------------------------------------------------- Plan hash value: 1390702853 ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 106 | 0 (0)| 00:00:01 | | 1 | NESTED LOOPS | | | | | | | 2 | NESTED LOOPS | | 1 | 106 | 0 (0)| 00:00:01 | | 3 | TABLE ACCESS BY INDEX ROWID| 使用_業者代表| 4 | 348 | 0 (0)| 00:00:01 | |* 4 | INDEX RANGE SCAN | 使用_業者代表| 2 | | 0 (0)| 00:00:01 | |* 5 | INDEX RANGE SCAN | 使用_個人情報| 1 | | 0 (0)| 00:00:01 | |* 6 | TABLE ACCESS BY INDEX ROWID | 使用_個人情報| 1 | 19 | 0 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 4 - access("A"."事業者登録番号"='1234567890') 5 - access("B"."個人識別番号" LIKE '8%' AND "B"."識別区分コード"='1') filter("B"."識別区分コード"='1' AND "B"."個人識別番号" LIKE '8%') 6 - filter("A"."個人番号"="B"."個人番号") Statistics ---------------------------------------------------------- 446 recursive calls 0 db block gets 85 consistent gets 7 physical reads 0 redo size 909 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 6 sorts (memory) 0 sorts (disk) 1 rows processed 暗号化後にSQL修正なしに遂行 SQL> SELECT a.事業者登録番号, a.代表者名, a.個人番号, b.個人識別番号, a.代表者電子メール 2 from 使用_業者代表者詳細 a, 使用_個人情報 b 3 where a.事業者登録番号 = '1234567890' 4 and a.個人番号 = b.個人番号 5 and b.識別区分コード ='1' 6 and b.個人識別番号 like '8%' 7 order by 代表者名 8 ; no rows selected Execution Plan ---------------------------------------------------------- Plan hash value: 1062875487 ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 112 | 7 (15)| 00:00:01 | | 1 | NESTED LOOPS | | | | | | | 2 | NESTED LOOPS | | 1 | 112 | 7 (15)| 00:00:01 | | 3 | TABLE ACCESS BY INDEX ROWID | 使用_業者代 | 4 | 348 | 0 (0)| 00:00:01 | |* 4 | INDEX RANGE SCAN | 使用_業者代 | 2 | | 0 (0)| 00:00:01 | | 5 | BITMAP CONVERSION TO ROWIDS | | | | | | | 6 | BITMAP AND | | | | | | | 7 | BITMAP CONVERSION FROM ROWIDS| | | | | | |* 8 | INDEX RANGE SCAN | 使用_個人情 | 1 | | 0 (0)| 00:00:01 | | 9 | BITMAP CONVERSION FROM ROWIDS| | | | | | | 10 | SORT ORDER BY | | | | | | |* 11 | DOMAIN INDEX | 個人識554970| 1 | | | | |* 12 | TABLE ACCESS BY INDEX ROWID | 使用_個人情 | 1 | 25 | 7 (15)| 00:00:01 | ------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 4 - access("A"."事業者登録番号"='1234567890') 8 - access("A"."個人番号"="個人番号") 11 - access("XSERVER"."ODEC_VARCHAR2_SEL"("個人識別番号",10,'AES','使用_個人情報#','個人識別番号') LIKE '8%') filter("XSERVER"."ODEC_VARCHAR2_SEL"("個人識別番号",10,'AES','使用_個人情報#','個人識別番号') LIKE '8%') 12 - filter("識別区分コード"='1') Statistics ---------------------------------------------------------- 6 recursive calls 0 db block gets 4 consistent gets 0 physical reads 0 redo size 663 bytes sent via SQL*Net to client 513 bytes received via SQL*Net from client 1 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 0 rows processed |
||
Cause |
Oracle optimizerがSQLを解釈するとき、where節にいろんな条件があり、その条件のカラムにindexが
それぞれ生成された場合、Btree IndexをBitmapにconversionしてPlanを策定・実行することになる。 その場合、性能が低下するケースが発生することがあり、where条件にdomain indexがある場合は wrong resultがreturnされる現象が発生することがある。 domain indexがあるときwrong resultがreturnされる現象は、現在オラクル本社にbugとして登録されbug fix patchを作っている。 |
||
Solution |
複合化viewでない暗号化tableを直接selectするようにSQLを修正
SQL> select a.事業者登録番号、a.代表者名、a.個人番号、xx1.dec_varchar2_sel(b.個人識別番号,10,'AES')、 a.代表者電子メール 2 from 使用_業者代表者詳細 a, 使用_個人情報# b 3 where a.事業者登録番号 = '1234567890' 4 and a.個人番号 = b.個人番号 5 and b.識別区分コード ='1' 6 and xx1.enc_index_varchar2(b.個人識別番号,'AES') like xx1.enc_index_varchar2_sel('8','AES')||'%' 7 order by 代表者名 8 ; Execution Plan ---------------------------------------------------------- Plan hash value: 813166258 -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 139 | 2 (0)| 00:00:01 | | 1 | NESTED LOOPS | | 1 | 139 | 2 (0)| 00:00:01 | | 2 | TABLE ACCESS BY INDEX ROWID| 使用_業者代 | 1 | 45 | 1 (0)| 00:00:01 | |* 3 | INDEX UNIQUE SCAN | SYS_C003909 | 1 | | 0 (0)| 00:00:01 | |* 4 | TABLE ACCESS BY INDEX ROWID| 使用_個人情 | 1 | 94 | 1 (0)| 00:00:01 | |* 5 | INDEX UNIQUE SCAN | 使用_個人情 | 1 | | 0 (0)| 00:00:01 | -------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("A"."事業者登録番号"='1234567890') 4 - filter("XX1"."ENC_INDEX_VARCHAR2"("個人識別番号",'AES') LIKE "XX1"."ENC_INDEX_VARCHAR2_SEL"('8','AES')||'%' AND "B"."識別区分コード"='1') 5 - access("A"."個人番号"="B"."個人番号") Statistics ---------------------------------------------------------- 711 recursive calls 4 db block gets 202 consistent gets 21 physical reads 0 redo size 942 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 16 sorts (memory) 0 sorts (disk) 1 rows processed |