-
April 2026 (1)
-
January 2026 (4)
-
December 2025 (1)
-
September 2025 (3)
-
August 2025 (1)
-
July 2025 (3)
-
June 2025 (1)
-
May 2025 (1)
-
February 2025 (1)
-
November 2024 (1)
-
October 2024 (1)
-
September 2024 (1)
-
April 2024 (3)
-
January 2024 (1)
-
October 2023 (1)
-
September 2023 (3)
-
August 2023 (1)
-
June 2023 (1)
-
April 2023 (3)
-
March 2023 (2)
-
February 2023 (1)
-
January 2023 (1)
-
December 2022 (2)
-
October 2022 (2)
-
September 2022 (2)
-
August 2022 (2)
-
July 2022 (1)
-
June 2022 (1)
-
May 2022 (2)
-
April 2022 (2)
-
March 2022 (1)
-
February 2022 (2)
-
January 2022 (1)
-
December 2021 (1)
-
November 2021 (1)
-
October 2021 (2)
-
July 2021 (1)
-
June 2021 (1)
-
May 2021 (1)
-
April 2021 (3)
-
March 2021 (2)
-
January 2021 (1)
-
November 2020 (3)
-
September 2020 (1)
-
August 2020 (1)
-
May 2020 (3)
-
April 2020 (3)
-
February 2020 (2)
-
January 2020 (1)
-
December 2019 (2)
-
August 2019 (2)
-
April 2019 (1)
-
November 2018 (5)
- Oracle row cache objects Event: 10222, Dtrace Script (I)
- Row Cache Objects, Row Cache Latch on Object Type: Plsql vs Java Call (Part-1) (II)
- Row Cache Objects, Row Cache Latch on Object Type: Plsql vs Java Call (Part-2) (III)
- Row Cache and Sql Executions (IV)
- Latch: row cache objects Contentions and Scalability (V)
-
October 2018 (2)
-
July 2018 (3)
-
April 2018 (1)
-
March 2018 (2)
-
February 2018 (1)
-
January 2018 (4)
-
October 2017 (2)
-
September 2017 (2)
-
July 2017 (3)
-
May 2017 (8)
- JDBC, Oracle object/collection, dbms_pickler, NOPARALLEL sys.type$ query
- PLSQL Context Switch Functions and Cost
- Oracle Datetime (1) - Concepts
- Oracle Datetime (2) - Examples
- Oracle Datetime (3) - Assignments
- Oracle Datetime (4) - Comparisons
- Oracle Datetime (5) - SQL Arithmetic
- Oracle Datetime (6) - PLSQL Arithmetic
-
March 2017 (3)
-
February 2017 (1)
-
January 2017 (1)
-
November 2016 (1)
-
September 2016 (2)
-
August 2016 (1)
-
June 2016 (1)
-
May 2016 (1)
-
April 2016 (1)
-
February 2016 (1)
-
January 2016 (3)
-
December 2015 (1)
-
November 2015 (1)
-
September 2015 (2)
-
August 2015 (1)
-
July 2015 (2)
-
June 2015 (1)
-
April 2015 (2)
-
January 2015 (1)
-
December 2014 (1)
-
November 2014 (2)
-
May 2014 (3)
-
March 2014 (2)
-
November 2013 (3)
-
September 2013 (1)
-
June 2013 (2)
-
April 2013 (2)
-
March 2013 (3)
-
December 2012 (1)
-
November 2012 (2)
-
July 2012 (1)
-
May 2012 (1)
-
April 2012 (1)
-
February 2012 (1)
-
November 2011 (2)
-
July 2011 (1)
-
May 2011 (3)
-
April 2011 (1)
Monday, April 27, 2026
One Oracle TDE Performance Test
In this Blog, we will test the performance difference of SQLs on TDE table and non TDE table.
Note: Tested in Oracle 19.27 on AIX and Linux
We create one TDE tablespace and one table on it, and also one test procedure.
We run both tests on AIX.
Here the TDE trc:
Here the perf top output of both tests runing on Linux.
Note: Tested in Oracle 19.27 on AIX and Linux
1. Test Setup
We create one TDE tablespace and one table on it, and also one test procedure.
drop tablespace test_ts_tde including contents and datafiles;
create tablespace test_ts_tde datafile '/oratestdb/oradata/testdb/test_ts_tde.dbf'
size 10m autoextend on maxsize 1g extent management local segment space management auto encryption default storage (encrypt);
drop table test_tab_tde;
create table test_tab_tde(grp number, id number, name varchar2(100), ts timestamp with time zone) tablespace test_ts_tde;
create index test_tab_tde_idx1 on test_tab_tde (grp, id, name, ts) tablespace test_ts_tde;
create index test_tab_tde_idx2 on test_tab_tde (grp, name) tablespace test_ts_tde;
create or replace procedure test_tab_tde_proc (p_grp_cnt number, p_id_cnt number) as
l_start number := dbms_utility.get_time;
type t_tab is table of test_tab_tde%rowtype;
l_tab t_tab := t_tab();
l_ins_cnt number := 0;
l_del_cnt number := 0;
l_upd_cnt number := 0;
l_sel_cnt number := 0;
begin
select ceil(level/p_id_cnt), level, rpad('abc_'||level, 100, 'x'), systimestamp bulk collect into l_tab from dual connect by level <= p_id_cnt;
l_start := dbms_utility.get_time;
for g in 1..p_grp_cnt loop
for i in 1..p_id_cnt loop
l_tab(i).grp := g;
end loop;
forall k in l_tab.first .. l_tab.last save exceptions
insert into test_tab_tde values l_tab(k);
l_ins_cnt := l_ins_cnt + p_id_cnt;
if mod(g, 2) = 1 then
delete from test_tab_tde where grp = g and rownum <= p_id_cnt;
l_del_cnt := l_del_cnt + sql%rowcount;
end if;
if mod(g, 2) = 0 then
update test_tab_tde set name = rpad('abc_'||id, 100, 'x') where grp = g and rownum <= p_id_cnt;
l_upd_cnt := l_upd_cnt + sql%rowcount;
end if;
for c in (select * from test_tab_tde where grp = g and rownum <= p_id_cnt)
loop
l_sel_cnt := l_sel_cnt + 1;
end loop;
commit;
end loop;
dbms_output.put_line('test_tab_tde elapsed='||round((dbms_utility.get_time-l_start)/100, 2)||
', Insert = '||l_ins_cnt||', Delete = '||l_del_cnt||', Update = '||l_upd_cnt||', Select = '||l_sel_cnt);
end;
/
Similarily, we create one NON TDE tablespace and one table on it, and also one test procedure.
drop tablespace test_ts_non including contents and datafiles;
create tablespace test_ts_non datafile '/oratestdb/oradata/testdb/test_ts_non.dbf'
size 10m autoextend on maxsize 1g extent management local segment space management auto;
drop table test_tab_non;
create table test_tab_non(grp number, id number, name varchar2(100), ts timestamp with time zone) tablespace test_ts_non;
create index test_tab_non_idx1 on test_tab_non (grp, id, name, ts) tablespace test_ts_non;
create index test_tab_non_idx2 on test_tab_non (grp, name) tablespace test_ts_non;
create or replace procedure test_tab_non_proc (p_grp_cnt number, p_id_cnt number) as
l_start number := dbms_utility.get_time;
type t_tab is table of test_tab_non%rowtype;
l_tab t_tab := t_tab();
l_ins_cnt number := 0;
l_del_cnt number := 0;
l_upd_cnt number := 0;
l_sel_cnt number := 0;
begin
select ceil(level/p_id_cnt), level, rpad('abc_'||level, 100, 'x'), systimestamp bulk collect into l_tab from dual connect by level <= p_id_cnt;
l_start := dbms_utility.get_time;
for g in 1..p_grp_cnt loop
for i in 1..p_id_cnt loop
l_tab(i).grp := g;
end loop;
forall k in l_tab.first .. l_tab.last save exceptions
insert into test_tab_non values l_tab(k);
l_ins_cnt := l_ins_cnt + p_id_cnt;
if mod(g, 2) = 1 then
delete from test_tab_non where grp = g and rownum <= p_id_cnt;
l_del_cnt := l_del_cnt + sql%rowcount;
end if;
if mod(g, 2) = 0 then
update test_tab_non set name = rpad('abc_'||id, 100, 'x') where grp = g and rownum <= p_id_cnt;
l_upd_cnt := l_upd_cnt + sql%rowcount;
end if;
for c in (select * from test_tab_non where grp = g and rownum <= p_id_cnt)
loop
l_sel_cnt := l_sel_cnt + 1;
end loop;
commit;
end loop;
dbms_output.put_line('test_tab_non elapsed='||round((dbms_utility.get_time-l_start)/100, 2)||
', Insert = '||l_ins_cnt||', Delete = '||l_del_cnt||', Update = '||l_upd_cnt||', Select = '||l_sel_cnt);
end;
/
2. Run both tests with SQL trace
We run both tests on AIX.
SQL > exec test_tab_tde_proc(1e4, 100);
test_tab_tde elapsed=91.65, Insert = 1000000, Delete = 500000, Update = 500000, Select = 500000
SQL > exec test_tab_non_proc(1e4, 100);
test_tab_non elapsed=42.31, Insert = 1000000, Delete = 500000, Update = 500000, Select = 500000
The elapsed time for TDE operations is more than double the time required for non-TDE operations.Here the TDE trc:
********************************************************************************
INSERT INTO test_TAB_TDE VALUES(:B1 ,:B2 ,:B3 ,:B4 )
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 10000 20.99 37.88 8 117577 1458787 1000000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 10001 20.99 37.88 8 117577 1458787 1000000
********************************************************************************
DELETE FROM test_TAB_TDE WHERE GRP = :B2 AND ROWNUM <= :B1
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 2 0
Execute 5000 18.87 33.92 0 24883 3593457 500000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 5001 18.87 33.92 0 24883 3593459 500000
********************************************************************************
SELECT * FROM test_TAB_TDE WHERE GRP = :B2 AND ROWNUM <= :B1
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 2 0
Execute 10000 0.73 1.32 0 0 0 0
Fetch 15000 0.59 1.05 0 61687 0 500000
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 25001 1.33 2.38 0 61687 2 500000
********************************************************************************
UPDATE test_TAB_TDE SET NAME = RPAD('abc_'||ID, 100, 'x') WHERE GRP = :B2 AND ROWNUM <= :B1
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 2 0
Execute 5000 7.93 14.24 0 19816 520264 500000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 5001 7.93 14.24 0 19816 520266 500000
Here the non TDE trc:
********************************************************************************
INSERT INTO test_TAB_NON VALUES(:B1 ,:B2 ,:B3 ,:B4 )
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 10000 9.57 16.73 8 119206 1430838 1000000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 10001 9.57 16.73 8 119206 1430838 1000000
********************************************************************************
DELETE FROM test_TAB_NON WHERE GRP = :B2 AND ROWNUM <= :B1
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 5000 7.76 13.48 0 24835 3592775 500000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 5001 7.76 13.48 0 24835 3592775 500000
********************************************************************************
SELECT * FROM test_TAB_NON WHERE GRP = :B2 AND ROWNUM <= :B1
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 10000 0.73 1.27 0 0 0 0
Fetch 15000 0.58 1.00 0 61647 0 500000
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 25001 1.31 2.27 0 61647 0 500000
********************************************************************************
UPDATE test_TAB_NON SET NAME = RPAD('abc_'||ID, 100, 'x') WHERE GRP = :B2 AND ROWNUM <= :B1
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 5000 3.94 6.82 0 19815 520240 500000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 5001 3.94 6.82 0 19815 520240 500000
Above traces showed that although Consistent Gets ("query") and Current Gets ("current") stats are very closed, TDE doubled elaspsed time compared to non-TDE. All 4 SQLs are CPU intensive (the differences between "cpu" and "elapsed" are due to AIX special accounting).
3. Perf TOP
Here the perf top output of both tests runing on Linux.
-- TDE
SQL > exec test_tab_tde_proc(1e4, 100);
test_tab_tde elapsed=24.86, Insert = 1000000, Delete = 500000, Update = 500000, Select = 500000
$ > perf top -p 1438084 -d 2
Overhead Shared Object Symbol
5.76% oracle [.] l9_EncryptCFB128_RIJ128_AES_NI.key_128_s
5.05% oracle [.] kcbchg1_main
4.14% oracle [.] kcrfw_redo_gen_ext
3.58% oracle [.] __intel_avx_rep_memcpy
3.40% [vdso] [.] __vdso_clock_gettime
2.34% oracle [.] kcbgcur
2.32% oracle [.] __intel_avx_rep_memset
2.03% oracle [.] kdkcmp1
1.65% oracle [.] kcrfw_enc_redo_gen
1.58% oracle [.] kcrfw_copy_cv
1.56% oracle [.] lxoCpStr
1.28% oracle [.] kcbget
1.25% oracle [.] kcbklbc
1.21% oracle [.] l9_aes128_KeyExpansion_NI
-- Non TDE
SQL > exec test_tab_non_proc(1e4, 100);
test_tab_non elapsed=18.54, Insert = 1000000, Delete = 500000, Update = 500000, Select = 50000
$ > perf top -p 1438084 -d 2
Overhead Shared Object Symbol
6.40% oracle [.] kcbchg1_main
5.31% oracle [.] kcrfw_redo_gen_ext
4.24% oracle [.] __intel_avx_rep_memcpy
2.61% oracle [.] kcbgcur
2.45% oracle [.] lxoCpStr
2.31% oracle [.] kcrfw_copy_cv
2.13% oracle [.] kcbhfix_tail
2.12% oracle [.] kdkcmp1
1.61% oracle [.] kcoapl
1.58% [vdso] [.] __vdso_clock_gettime
1.56% oracle [.] ktuchg2
1.49% oracle [.] lxsCntDisp
1.41% oracle [.] kcbget
1.36% oracle [.] kdiins1
1.35% oracle [.] kcbklbc
1.28% oracle [.] kslfre
1.17% oracle [.] _intel_fast_memcpy
1.16% oracle [.] kslgetl
1.09% oracle [.] sxorchk
0.90% oracle [.] ksl_get_shared_latch_int
-- check AES-NI
$ > grep -o aes /proc/cpuinfo | head -n 1
aes
Subscribe to:
Comments (Atom)