Oracle 21版Database In-Memory LivaLabs实验(上)
概述
目前Oracle LiveLabs上关于Oracle Database In-Memory的内容已更新,主要变化为:
- 数据库使用21c
- 增加了对21c原生JSON的实验
- 增加了21c AIM HIGH级别的实验
这个实验的名称为Boost Analytics Performance with Oracle Database In-Memory。
实验帮助在这里。
实验环境描述
实验环境的生成需要约8分钟。这是一个2 OCPU(4 vCPU), 32G内存的机器。如果自己搭建环境,只需要16GB的内存就够了。
[oracle@dbhol:~]$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 2
Core(s) per socket: 2
Socket(s): 1
NUMA node(s): 1
Vendor ID: AuthenticAMD
CPU family: 25
Model: 1
Model name: AMD EPYC 7J13 64-Core Processor
Stepping: 1
CPU MHz: 2445.406
BogoMIPS: 4890.81
Virtualization: AMD-V
Hypervisor vendor: KVM
Virtualization type: full
L1d cache: 64K
L1i cache: 64K
L2 cache: 512K
L3 cache: 16384K
NUMA node0 CPU(s): 0-3
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm rep_good nopl cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy svm cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext perfctr_core invpcid_single ssbd ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 xsaves nt_good clzero xsaveerptr wbnoinvd arat npt nrip_save umip pku ospke vaes vpclmulqdq rdpid arch_capabilities[oracle@dbhol:~]$ free -gtotal used free shared buff/cache available
Mem: 31 3 17 6 10 21
Swap: 7 0 7
尽管提供了图形化VNC远程连接的方式,但也可以用putty直接登录虚机,这样更方便。方法请参见“Lab 1: Environment Setup”,此不赘述。
数据库版本为21.7,数据库是PDB1,用到了SSB和AIM两个schema:
Connected to:
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.7.0.0.0SQL> show pdbsCON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------2 PDB$SEED READ ONLY NO3 PDB1 READ WRITE NOSQL> select username from all_users where ORACLE_MAINTAINED != 'Y';USERNAME
--------------------------------------------------------------------------------
PDBADMIN
AIM
SSB
SSB schema中的5张标准表均启用了压缩,以下命令只是说明,无需运行:
alter table lineorder move compress basic;
alter table part move compress basic;
alter table date_dim move compress basic;
alter table supplier move compress basic;
alter table customer move compress basic;
alter table storage(buffer_pool keep);
同时也都放在了指定的buffer pool中,以下命令只是说明,无需运行:
alter table lineorder storage(buffer_pool keep);
alter table part storage(buffer_pool keep);
alter table date_dim storage(buffer_pool keep);
alter table supplier storage(buffer_pool keep);
alter table customer storage(buffer_pool keep);
这5张表的数据生成可用以下命令:
./dbgen -s 10 -T c
./dbgen -s 10 -T s
./dbgen -s 10 -T p
./dbgen -s 10 -T l
./dbgen -s 1 -T d
然后导入数据后,将lineorder变为分区表,并删除2个分区:
alter table lineorder modify partition by range(lo_orderdate)
(partition part_1992 values less than ('19930101'),partition part_1993 values less than ('19940101'),partition part_1994 values less than ('19950101'),partition part_1995 values less than ('19960101'),partition part_1996 values less than ('19970101'),partition part_1997 values less than ('19980101'),partition part_1998 values less than ('19990101')
);alter table lineorder drop partition part_1992;
alter table lineorder drop partition part_1993;
实验2:初始化环境
任务 1:为内存中用例初始化数据库
首先,需要用oracle用户下载实验脚本:
clear
cd ~oracle/labs
rm -rf ~oracle/labs/*
wget -O novnc-inmemory-21c.zip https://objectstorage.us-ashburn-1.oraclecloud.com/p/7lzqJmKirEWwAc-e4XbZhV0A9ZYzqv7jU6HRhADWpR5zbhHb3x3rKjZV3m5ktDD0/n/c4u04/b/livelabsfiles/o/labfiles/novnc-inmemory-21c.zip
unzip -qo novnc-inmemory-21c.zip
rm -f novnc-inmemory-21c.zip
cd inmemory
ls -ltrh
由于此环境的模板有2个CDB,CDB1和CDB2。而我们只需要CDB1,因此需要停掉CDB2:
sudo systemctl stop oracle-database
sudo sed -i -e 's|CDB2.*$|CDB2:/opt/oracle/product/21c/dbhome_1:N|g' /etc/oratab
sudo systemctl start oracle-database
ps -ef|grep ora_|grep pmon|grep -v grep
而方法是在oratab中将CDB2的条目改为N:
$ cat /etc/oratab
CDB1:/opt/oracle/product/21c/dbhome_1:Y
CDB2:/opt/oracle/product/21c/dbhome_1:N
修改~/labs/inmemory目录下,以下两个文件中ssb和aim用户的口令:
$ ls *login.sql
aim_login.sql imlogin.sql
任务 2:启用In-Memory
运行以下脚本,初始化环境变量:
. ~/.set-env-db.sh CDB1
我们来研究下这个脚本,其中有很多值得学习之处,详见其中的中文注释:
#!/bin/bash
# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.################################################################################
#
# Name:set-env-db.sh
#
# Description: Script to set the database environment (single instance) in multiple
# Oracle homes setup
#
#
# Pre-requisite: This should be executed as the user that owns Oracle DB binaries.
#
# AUTHOR(S)
# -------
# Rene Fontcha, Oracle LiveLabs Platform Lead
#
# MODIFIED Date Comments
# -------- ---------- -----------------------------------
# Rene Fontcha 10/18/2021 Initial Creation
# Rene Fontcha 05/19/2022 Replaced Public IP lookup routine
# Rene Fontcha 07/19/2022 Added "Oracle LiveLabs" branding banner
#
###############################################################################
PRIVATE_IP=$(cat /etc/hosts | grep $(hostname) | grep -v grep |tail -1 | awk '{print $1}')
HOSTNAME=$(hostname)## 如果有多个私网IP地址,以下会得到所有列表
if [ -z ${PRIVATE_IP} ]; thenPRIVATE_IP=$(oci-metadata -g privateIp | sed -n -e 's/^.*Private IP address: //p')
fiexport PRIVATE_IP
## 得到公网地址,这个命令不错
export PUBLIC_IP=$(curl -s ifconfig.me)
unset ORACLE_SIDif [ -f /etc/oratab ]; thenOTAB=/etc/orataboratab_exist=Y
elif [ -f /var/opt/oracle/oratab ]; thenOTAB=/var/opt/oracle/orataboratab_exist=Y
elseoratab_exist=Necho 'oratab file not found.'
fi
load_env_header() {clearecho "================================================================================"
## figlet 需 yum安装,类似于banner,-c表示居中
## figlet -c Oracle LiveLabsecho "================================================================================"echo " ENV VARIABLES "echo "--------------------------------------------------------------------------------"
}load_db_env() {export ORAENV_ASK=NO. oraenv >/dev/nullexport ORAENV_ASK=YESexport OH=${ORACLE_HOME}
## 这个确定TNS_ADMIN的方法不错,即21c增加的orabasehomeif [ -f ${OH}/bin/orabasehome ]; thenexport ORACLE_BASE_HOME=$(orabasehome)export TNS_ADMIN=${ORACLE_BASE_HOME}/network/adminelseexport TNS_ADMIN=${OH}/network/adminfiexport LD_LIBRARY_PATH=$OH/libexport PATH=${OH}/bin:${OH}/OPatch:${JAVA_HOME}/bin:/bin:/usr/ccs/bin:/usr/sfw/bin:/usr/bin:/usr/sbin:/usr/ucb:/etc:/usr/local/bin:/usr/dt/bin:/usr/openwin/bin:/opt/sfw/bin/:.:~:/sbin:/usr/X11R6/bin:$PATHalias ssql="$OH/bin/sql / as sysdba"echo " . ORACLE_BASE = ${ORACLE_BASE}"if [ -f ${OH}/bin/orabasehome ]; thenecho " . ORACLE_BASE_HOME = ${ORACLE_BASE_HOME}"fiecho " . ORACLE_HOME = ${OH}"echo " . ORACLE_SID = ${ORACLE_SID}"echo " . PRIVATE_IP = ${PRIVATE_IP}"echo " . PUBLIC_IP = ${PUBLIC_IP}"echo " . HOSTNAME = ${HOSTNAME}"echo "--------------------------------------------------------------------------------"echo " Database ENV set for ${ORACLE_SID} "echo " "echo " Run this to reload/setup the Database ENV: source /usr/local/bin/.set-env-db.sh"echo "--------------------------------------------------------------------------------"echo "================================================================================"echo " "
}
#
#############################################################################
# Display Info
# ---------------------------------------------------------------------------case ${oratab_exist} in
Y)if [ -z $1 ]; thenSIDLIST=$(egrep -v -e '^$|#|\*' ${OTAB} | cut -f1 -d:)echo ""echo "List of Database Instances"printf "\n%-2s %-15s \n" "#" "ORACLE_SID"echo "-- ----------"PS3=$'\n'"Select a number from the list (1-n): "select sid in ${SIDLIST}; doecho ""if [ -n $sid ]; thenORACLE_SID=$sidload_env_headerload_db_envbreakfidoneelseload_env_headerif egrep -v '#|\*' ${OTAB} | grep -w "${1}:" >/dev/null; thenORACLE_SID=$1load_db_envelseecho " . PRIVATE_IP = ${PRIVATE_IP}"echo " . PUBLIC_IP = ${PUBLIC_IP}"echo " . HOSTNAME = ${HOSTNAME}"echo "--------------------------------------------------------------------------------"echo " Database ENV is not set "echo " Supplied ORACLE_SID ($1) not found in $OTAB. "echo " "echo " Run this to reload/setup the Database ENV: source /usr/local/bin/.set-env-db.sh"echo "--------------------------------------------------------------------------------"echo "================================================================================"echo " "fifi;;
*)load_env_headerecho " . PRIVATE_IP = ${PRIVATE_IP}"echo " . PUBLIC_IP = ${PUBLIC_IP}"echo " . HOSTNAME = ${HOSTNAME}"echo "--------------------------------------------------------------------------------"echo "================================================================================"echo " ";;
esac
这个脚本里还有一个figlet命令,类似于banner:
$ figlet "Oracle LiveLabs"___ _ _ _ _ _/ _ \ _ __ __ _ ___| | ___ | | (_)_ _____| | __ _| |__ ___
| | | | '__/ _` |/ __| |/ _ \ | | | \ \ / / _ \ | / _` | '_ \/ __|
| |_| | | | (_| | (__| | __/ | |___| |\ V / __/ |__| (_| | |_) \__ \\___/|_| \__,_|\___|_|\___| |_____|_| \_/ \___|_____\__,_|_.__/|___/$ banner "Oracle LiveLabs"####### ###### # ##### # ####### # ### # # ####### # # ###### #####
# # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # #
# # ###### # # # # ##### # # # # ##### # # # ###### #####
# # # # ####### # # # # # # # # # ####### # # #
# # # # # # # # # # # # # # # # # # # # # #
####### # # # # ##### ####### ####### ####### ### # ####### ####### # # ###### #####
接下来设置数据库参数:
connect / as sysdba
alter system set heat_map=ON scope=spfile;
alter system set sga_max_size=8G scope=spfile;
alter system set sga_target=8G scope=spfile;
alter system set db_keep_cache_size=3000M scope=spfile;
alter system set pga_aggregate_target=2500M scope=spfile;
alter system set inmemory_size=3300M scope=spfile;
alter system set inmemory_max_populate_servers=4 scope=spfile;
alter system set inmemory_virtual_columns=enable scope=spfile;
alter system set "_inmemory_64k_percent"=5 scope=spfile;
alter system set "_inmemory_small_segment_threshold"=0 scope=spfile;
alter system set "_optimizer_use_feedback"=FALSE scope=spfile;
alter system set "_imado_enable_coloptim"=FALSE scope=spfile;
查看隐含参数的脚本如下,详见MOS How To Query And Change The Oracle Hidden Parameters In Oracle 10g and Later (文档 ID 315631.1):
set lines 150
col parameter for a40
col "Session Value" for a20
col "Instance Value" for a20
SELECT a.ksppinm "Parameter", b.KSPPSTDF "Default Value",b.ksppstvl "Session Value", c.ksppstvl "Instance Value",decode(bitand(a.ksppiflg/256,1),1,'TRUE','FALSE') IS_SESSION_MODIFIABLE,decode(bitand(a.ksppiflg/65536,3),1,'IMMEDIATE',2,'DEFERRED',3,'IMMEDIATE','FALSE') IS_SYSTEM_MODIFIABLE
FROM x$ksppi a,x$ksppcv b,x$ksppsv c
WHERE a.indx = b.indx
AND a.indx = c.indx
AND a.ksppinm LIKE '/&1' escape '/'
/
以下是一些关键隐含参数的默认值和说明:
-- _inmemory_small_segment_threshold默认值为64K,表示小于此值的segment不会考虑发布到IMCS
-- _inmemory_64k_percent表示 in-memory area中元数据和数据的分配比例,默认为3比7
-- _imado_enable_coloptim没找到说明,
Parameter Default V Session Value Instance Value IS_SE IS_SYSTEM
---------------------------------------- --------- -------------------- -------------------- ----- ---------
_inmemory_small_segment_threshold FALSE 65536 65536 FALSE IMMEDIATE
_inmemory_64k_percent FALSE 30 30 FALSE FALSE
_optimizer_use_feedback FALSE TRUE TRUE TRUE IMMEDIATE
_imado_enable_coloptim FALSE TRUE TRUE TRUE IMMEDIATE
_optimizer_use_feedback是11g引入的特性,详见以下文章:
- Trivial Research on the Cardinality Feedback on 11gR2
- Adaptive Optimisation ?
- Hidden and Undocumented “Cardinality Feedback”
重启使其生效:
shutdown immediate
startup
exit
实验 3:设置 In-Memory Column Store
此实验的主要脚本执行序列如下,后面会详述:
@01_show_parms.sql
@02_show_sga.sql
@03_im_usage.sql
@04_im_alter_table.sql
@05_im_attributes.sql
每次实验前,都需要执行以下:
. ~/.set-env-db.sh CDB1
进入setup目录,登录数据库:
cd /home/oracle/labs/inmemory/setup
sqlplus ssb/Ora_DB4U@localhost:1521/pdb1
先去除inmemory属性,原文中少了SUPPLIER表:
alter table SSB.DATE_DIM no inmemory;
alter table SSB.PART no inmemory;
alter table SSB.CUSTOMER no inmemory;
alter table SSB.SUPPLIER no inmemory;
alter table SSB.LINEORDER modify partition PART_1996 no inmemory;
alter table SSB.LINEORDER modify partition PART_1998 no inmemory;
alter table SSB.LINEORDER modify partition PART_1995 no inmemory;
alter table SSB.LINEORDER modify partition PART_1997 no inmemory;
alter table SSB.LINEORDER modify partition PART_1994 no inmemory;
查看内存设置:
SQL> @01_show_parms.sql
Connected.
SQL>
SQL> -- Shows the SGA init.ora parameters
SQL>
SQL> show parameter sgaNAME TYPE VALUE
------------------------------------ ----------- ------------------------------
allow_group_access_to_sga boolean FALSE
lock_sga boolean FALSE
pre_page_sga boolean TRUE
sga_max_size big integer 8G
sga_min_size big integer 0
sga_target big integer 0
SQL>
SQL> show parameter db_keep_cache_sizeNAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_keep_cache_size big integer 3008M
SQL>
SQL> show parameter heat_mapNAME TYPE VALUE
------------------------------------ ----------- ------------------------------
heat_map string ON
SQL>
SQL> show parameter inmemory_sizeNAME TYPE VALUE
------------------------------------ ----------- ------------------------------
inmemory_size big integer 3312M
SQL>
SQL> set echo off
可以看到我们修改了以下的默认参数:
- INMEMORY_SIZE由0改为3300M
- HEAT_MAP由OFF改为ON
- DB_KEEP_CACHE_SIZE由0改为3000M,以便行式内存和列式内存的性能差异。
查看SGA设置,SGA设置为8G,输出显示In-Memory Area已配置:
SQL> @02_show_sga.sql
Connected.
SQL> set numwidth 20
SQL>
SQL> -- Show SGA memory allocation
SQL>
SQL> show sgaTotal System Global Area 8589933480 bytes
Fixed Size 9706408 bytes
Variable Size 486539264 bytes
Database Buffers 4613734400 bytes
Redo Buffers 7069696 bytes
In-Memory Area 3472883712 bytes
SQL>
SQL> set echo off
SGA 由固定大小、可变大小、数据库缓冲区和重做缓冲区组成。 由于我们设置了 INEMMORY_SIZE 参数,我们还可以看到在 SGA 中分配的 In-Memory Area。
In-Memory 区域被细分为两个池:一个 1MB 的池用于存储填充在 IM 列存储中的实际列格式数据,一个 64KB 的池用于存储有关填充在 IM 列存储中的对象的元数据。 V$INMEMORY_AREA 视图显示了在 IM 列存储中分配和使用的总内存。
SQL> @03_im_usage.sql
Connected.
SQL> column pool format a10;
SQL> column alloc_bytes format 999,999,999,999,999
SQL> column used_bytes format 999,999,999,999,999
SQL>
SQL> -- Show total column store usage
SQL>
SQL> SELECT pool, alloc_bytes, used_bytes, populate_status, con_id2 FROM v$inmemory_area;POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
---------- -------------------- -------------------- -------------------------- --------------------
1MB POOL 3,252,682,752 0 DONE 3
64KB POOL 201,326,592 0 DONE 3SQL>
SQL> set echo off
可以看到这两个池的比例为95比5:
SQL> select 3252682752/(3252682752+201326592) from dual;3252682752/(3252682752+201326592)
---------------------------------.9417122040072859745
为SSB schema中的5张表设置inmemory属性:
SQL> @04_im_alter_table.sql
Connected.
SQL>
SQL> -- Enable tables for in-memory
SQL>
SQL> alter table LINEORDER inmemory;Table altered.SQL> alter table PART inmemory;Table altered.SQL> alter table CUSTOMER inmemory;Table altered.SQL> alter table SUPPLIER inmemory;Table altered.SQL> alter table DATE_DIM inmemory;Table altered.SQL>
SQL> set echo off
显示属性:
SQL> @05_im_attributes.sql
Connected.
SQL>
SQL> -- Show table attributes
SQL>
SQL> select table_name, NULL as partition_name, buffer_pool, compression, compress_for, inmemory,2 inmemory_priority, inmemory_distribute, inmemory_compression3 from user_tables4 where table_name in ('DATE_DIM','PART','SUPPLIER','CUSTOMER')5 UNION ALL6 select table_name, partition_name, buffer_pool, compression, compress_for, inmemory,7 inmemory_priority, inmemory_distribute, inmemory_compression8 from user_tab_partitions9 where table_name = 'LINEORDER';DISK INMEMORY INMEMORY INMEMORY
TABLE_NAME PARTITION_NAME BUFFER_POOL COMPRESSION COMPRESS_FOR INMEMORY PRIORITY DISTRIBUTE COMPRESSION
------------ --------------- ----------- ----------- ------------ -------- ---------- ------------ --------------
CUSTOMER KEEP ENABLED BASIC ENABLED NONE AUTO FOR QUERY LOW
DATE_DIM KEEP ENABLED BASIC ENABLED NONE AUTO FOR QUERY LOW
PART KEEP ENABLED BASIC ENABLED NONE AUTO FOR QUERY LOW
SUPPLIER KEEP ENABLED BASIC ENABLED NONE AUTO FOR QUERY LOW
LINEORDER PART_1994 KEEP ENABLED BASIC ENABLED HIGH AUTO FOR QUERY LOW
LINEORDER PART_1995 KEEP ENABLED BASIC ENABLED HIGH AUTO FOR QUERY LOW
LINEORDER PART_1996 KEEP ENABLED BASIC ENABLED HIGH AUTO FOR QUERY LOW
LINEORDER PART_1997 KEEP ENABLED BASIC ENABLED HIGH AUTO FOR QUERY LOW
LINEORDER PART_1998 KEEP ENABLED BASIC ENABLED HIGH AUTO FOR QUERY LOW9 rows selected.SQL>
SQL> set echo off
通过全表扫描发布到IMCS:
SQL> @06_im_start_pop.sql
Connected.
SQL>
SQL> -- Access tables enabled for in-memory to start population
SQL>
SQL> select /*+ full(LINEORDER) noparallel(LINEORDER) */ count(*) from LINEORDER;COUNT(*)
--------------------41760941SQL> select /*+ full(PART) noparallel(PART) */ count(*) from PART;COUNT(*)
--------------------800000SQL> select /*+ full(CUSTOMER) noparallel(CUSTOMER) */ count(*) from CUSTOMER;COUNT(*)
--------------------300000SQL> select /*+ full(SUPPLIER) noparallel(SUPPLIER) */ count(*) from SUPPLIER;COUNT(*)
--------------------20000SQL> select /*+ full(DATE_DIM) noparallel(DATE_DIM) */ count(*) from DATE_DIM;COUNT(*)
--------------------2556SQL>
SQL> set echo off
注意 FULL 和 NOPARALLEL 提示。 他们可确保表数据也被读入定义的 KEEP 池。 这仅针对本实验进行,以便我们可以向您展示基于内存的数据库内存列格式与传统行格式的性能比较。 这不是启动 Database In-Memory 填充所必需的。
populate_wait是同步发布的PL/SQL过程,但此处也可以用于查询发布状态:
SQL> @07_populate_wait.sql
Connected.
SQL>
SQL> -- Show populate_wait query
SQL>
SQL> -- Return code:
SQL> -- -1 = POPULATE_TIMEOUT
SQL> -- 0 = POPULATE_SUCCESS
SQL> -- 1 = POPULATE_OUT_OF_MEMORY
SQL> -- 2 = POPULATE_NO_INMEMORY_OBJECTS
SQL> -- 3 = POPULATE_INMEMORY_SIZE_ZERO
SQL>
SQL> select dbms_inmemory_admin.populate_wait(priority=>'NONE',percentage=>100,timeout=>60) pop_status from dual;POP_STATUS
--------------------0SQL>
SQL> set echo off
确认发布已完成,并且没有内存不够的现象:
SQL> @08_im_populated.sql
Connected.
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 order by owner, segment_name, partition_name;In-Memory Bytes
OWNER SEGMENT_NAME PARTITION_NAME POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB CUSTOMER COMPLETED 24,928,256 23,199,744 0
SSB DATE_DIM COMPLETED 122,880 1,179,648 0
SSB LINEORDER PART_1994 COMPLETED 563,609,600 478,281,728 0
SSB LINEORDER PART_1995 COMPLETED 563,470,336 478,281,728 0
SSB LINEORDER PART_1996 COMPLETED 565,018,624 480,378,880 0
SSB LINEORDER PART_1997 COMPLETED 563,322,880 479,330,304 0
SSB LINEORDER PART_1998 COMPLETED 329,015,296 280,690,688 0
SSB PART COMPLETED 56,893,440 16,973,824 0
SSB SUPPLIER COMPLETED 1,769,472 2,228,224 09 rows selected.SQL>
SQL> set echo off
查看in-memory area的使用情况,数据部分已用了近70%:
SQL> @09_im_usage.sql
Connected.
SQL> column pool format a10;
SQL> column alloc_bytes format 999,999,999,999,999
SQL> column used_bytes format 999,999,999,999,999
SQL>
SQL> -- Show total column store usage
SQL>
SQL> SELECT pool, alloc_bytes, used_bytes, populate_status, con_id2 FROM v$inmemory_area;POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
---------- -------------------- -------------------- --------------- --------------------
1MB POOL 3,252,682,752 2,234,515,456 DONE 3
64KB POOL 201,326,592 6,029,312 DONE 3SQL>
SQL> set echo off
实验 4:查询In-Memory Column Store
此实验的主要脚本执行序列如下,后面会详述:
@01_im_query_stats.sql
@02_buffer_query_stats.sql
@03_single_key_im.sql
@04_single_key_buffer.sql
@05_index_comparison.sql
@06_storage_index.sql
@07_multi_preds.sql
每次实验前,都需要执行以下:
. ~/.set-env-db.sh CDB1
进入queries目录,登录数据库:
cd /home/oracle/labs/inmemory/queries
sqlplus ssb/Ora_DB4U@localhost:1521/pdb1
调整显示:
set pages 9999
set lines 150
先来看In-Memory全表扫描:
SQL> @01_im_query_stats.sql
-- 耗时
Elapsed: 00:00:00.02
-- 执行计划
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 4376 (100)| | | |
| 1 | SORT AGGREGATE | | 1 | 9 | | | | |
| 2 | PARTITION RANGE ALL | | 41M| 358M| 4376 (27)| 00:00:01 | 1 | 5 |
| 3 | TABLE ACCESS INMEMORY FULL| LINEORDER | 41M| 358M| 4376 (27)| 00:00:01 | 1 | 5 |
------------------------------------------------------------------------------------------------------------ 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 23
IM scan CUs columns accessed 156
IM scan CUs memcompress for query low 78
IM scan CUs pcode aggregation pushdown 156
IM scan rows 41760941
IM scan rows pcode aggregated 41760941
IM scan rows projected 78
IM scan rows valid 41760941
physical reads 79
session logical reads 323922
session logical reads - IM 315483
session pga memory 19335472
table scans (IM) 513 rows selected.
再来看buffer cache中的全表扫描(通过/*+ NO_INMEMORY */
提示禁用了In-Memory),此查询要多执行几次,以保证会话统计信息中没有物理读。结果表明慢了近200倍:
SQL>
-- 耗时
Elapsed: 00:00:03.94-- 执行计划
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 86830 (100)| | | |
| 1 | SORT AGGREGATE | | 1 | 9 | | | | |
| 2 | PARTITION RANGE ALL| | 41M| 358M| 86830 (2)| 00:00:04 | 1 | 5 |
| 3 | TABLE ACCESS FULL | LINEORDER | 41M| 358M| 86830 (2)| 00:00:04 | 1 | 5 |
---------------------------------------------------------------------------------------------------- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 405
IM scan segments disk 5
session logical reads 320529
session pga memory 19269936
在本例中,为什么列式内存比行式内存快很多?
IM 列存储只需扫描两列 - LO_ORDTOTALPRICE 和 LO_QUANTITY - 而行存储必须扫描每一行中的所有列,直到它到达 LO_ORDTOTALPRICE 和 LO_QUANTITY 列。 IM 列存储还受益于内存中数据压缩,因此扫描的数据量要少得多。最后,列格式可以利用 SIMD 矢量处理(单指令处理多个数据值)。 SIMD 向量处理不是一次评估列中的每个条目,而是允许在单个 CPU 指令中一起评估一组列值。
执行计划显示优化器选择了内存扫描,但要确认使用了 IM 列存储,我们需要检查会话级别的统计信息。请注意,在内存查询中显示了几个 IM 统计信息(对于本实验,我们只显示了一些关键统计信息——还有更多!)。我们现在唯一真正感兴趣的是“IM scan rows”。
IM scan rows表示扫描的内存行数。
当我们的查询对 LINEORDER 表进行全表扫描时,该会话统计显示我们从 IM 列存储中扫描了大约 4100 万行。 请注意,在第二个缓冲区缓存查询中,没有显示该统计信息。 只有一个内存统计显示,“IM scan segments disk”,值为 1。这意味着即使 LINEORDER 表在 IM 列存储(IM 段)中,我们实际上从列存储之外扫描该段缓冲区缓存。 由于我们完全缓存了 KEEP 池中的表,因此我们正在进行内存与内存比较,在这种情况下,我们可以验证查询没有物理 IO(如果显示少量物理 IO,则尝试再次运行它以确保 它完全缓存在 KEEP 池中)。
再来看单个值查询,理论上IMCS是不适合的:
SQL> @03_single_key_im.sql
-- 耗时
Elapsed: 00:00:00.01-- 执行计划
---------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3570 (100)| | | |
| 1 | PARTITION RANGE ALL | | 4 | 68 | 3570 (10)| 00:00:01 | 1 | 5 |
|* 2 | TABLE ACCESS INMEMORY FULL| LINEORDER | 4 | 68 | 3570 (10)| 00:00:01 | 1 | 5 |
---------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - inmemory("LO_ORDERKEY"=5000000)filter("LO_ORDERKEY"=5000000)
请注意,在执行计划的谓词信息中,您会看到“inmemory”和“filter”。 这表明过滤谓词(即“LO_ORDERKEY”=5000000)被“推送”到 LINEORDER 表的扫描中,而不必在检索到值后进行评估。 这是 Database In-Memory 加快查询速度的重要方式之一。
然后在行式内存中运行同样的查询,此时还没有用到索引。和列式内存比,性能差243倍:
SQL>
-- 耗时
Elapsed: 00:00:02.43-- 执行计划
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 86485 (100)| | | |
| 1 | PARTITION RANGE ALL| | 4 | 68 | 86485 (1)| 00:00:04 | 1 | 5 |
|* 2 | TABLE ACCESS FULL | LINEORDER | 4 | 68 | 86485 (1)| 00:00:04 | 1 | 5 |
-------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - filter("LO_ORDERKEY"=5000000)
请注意,在执行计划的谓词信息中,您只能看到“过滤器”。 这表明过滤谓词(即“LO_ORDERKEY”=5000000)是在检索到值之后评估的。 而Database In-Memory却可以在扫描数据期间进行过滤。
行式内存加索引的效果如何呢?我们启用了之前隐藏的索引:
SQL> @05_index_comparison.sql-- 耗时
Elapsed: 00:00:00.01-- 执行计划
---------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 12 (100)| | | |
| 1 | PARTITION RANGE ALL | | 4 | 68 | 12 (0)| 00:00:01 | 1 | 5 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| LINEORDER | 4 | 68 | 12 (0)| 00:00:01 | 1 | 5 |
|* 3 | INDEX RANGE SCAN | LINEORDER_I2 | 4 | | 11 (0)| 00:00:01 | 1 | 5 |
---------------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------3 - access("LO_ORDERKEY"=5000000)
此时行式内存和列式内存的性能基本相同。请注意,在执行计划中,对 LINEORDER_I2 索引执行了 INDEX RANGE SCAN。 这是 Oracle 实施 Database In-Memory 的方式的另一大好处。 优化器基于成本能够确定访问数据的最有效方式。 在此示例中,如果有适当的索引可用,优化器决定使用该索引更有效。 这就是无需更改应用程序 SQL 即可使用 Database In-Memory 的原因,也是 Database In-Memory 可用于混合工作负载环境(即同时使用事务和分析)的原因。
如果您没有优化器可以使用的索引,但您已经在 IM 列存储中填充了数据,该怎么办。 性能会受到影响吗? Database In-Memory 的另一个特性称为 In-Memory Storage Indexes。 我们将重复第 3 步中的查询,但这次我们将包含更多信息,看看我们是否能弄清楚幕后发生了什么。
SQL> @06_storage_index.sql
-- 耗时,和查询3一样-- 执行计划,和查询3一样-- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 4
IM scan CUs columns accessed 7
IM scan CUs memcompress for query low 78
IM scan CUs pruned 73
IM scan rows 41760941
IM scan rows projected 1
IM scan rows valid 2675664
IM scan segments minmax eligible 78
session logical reads 315634
session logical reads - IM 315483
session pga memory 18221360
table scans (IM) 512 rows selected.
这次我们包括了查询的会话统计信息。 注意两个关键统计数据。 第一个是“IM scan CUs memcompress for query low”,此处为78。 这告诉我们数据填充到了多少个 IMCU。 第二个重要的统计数据是“IM scan CUs pruned”,此处为73。 请注意,这个数字几乎与 IMCU 的总数一样大。 这意味着 Database In-Memory 能够避免扫描绝大部分的数据。 这是因为在填充时为每个 IMCU 中的每组列值创建了内存中存储索引,其中包含 MIN 和 MAX 值。 在扫描期间,这些 MIN 和 MAX 值可以与过滤谓词进行比较,因此可以略过不必扫描的列数据,从而提高性能。 毕竟,做某事最快的方法就是完全不做。
下一个是多谓词查询。传统上,您会创建一个多列索引。 In-Memory能与之抗衡吗?:
SQL> @07_multi_preds.sql
-- 耗时
Elapsed: 00:00:00.04-- 执行计划
---------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3329 (100)| | | |
| 1 | PARTITION RANGE ALL | | 6 | 264 | 3329 (4)| 00:00:01 | 1 | 5 |
|* 2 | TABLE ACCESS INMEMORY FULL| LINEORDER | 6 | 264 | 3329 (4)| 00:00:01 | 1 | 5 |
---------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - inmemory(("LO_CUSTKEY"=5641 AND "LO_SHIPMODE"='SHIP' AND "LO_ORDERPRIORITY"='5-LOW'))filter(("LO_CUSTKEY"=5641 AND "LO_SHIPMODE"='SHIP' AND "LO_ORDERPRIORITY"='5-LOW'))-- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 6
IM scan CUs columns accessed 169
IM scan CUs memcompress for query low 78
IM scan rows 41760941
IM scan rows projected 13
IM scan rows valid 41760941
IM scan segments minmax eligible 78
physical reads 4
session logical reads 315997
session logical reads - IM 315483
session pga memory 18417968
table scans (IM) 512 rows selected.
在此示例中,您可以在 Predicate Information 部分看到多个过滤谓词包含在“inmemory”函数中。 Database In-Memory 不限于仅将单个谓词推送到扫描中。 还有另一个重要的统计数据可用于衡量通过将谓词推送到扫描中节省了多少工作。 注意统计“IM scan rows projected”。 该值为 13,这正是查询返回的行数。 该统计数据表明,即使我们扫描了 4100 万行,我们也只返回了 13 行。 这是 Database In-Memory 比行存储快得多的另一个原因。
更为复杂的查询:
SQL>
-- 耗时
Elapsed: 00:00:00.05-- 执行计划
---------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 12736 (100)| | | |
| 1 | PARTITION RANGE ALL | | 7 | 84 | 4008 (20)| 00:00:01 | 1 | 5 |
|* 2 | TABLE ACCESS INMEMORY FULL | LINEORDER | 7 | 84 | 4008 (20)| 00:00:01 | 1 | 5 |
| 3 | SORT AGGREGATE | | 1 | 25 | | | | |
| 4 | PARTITION RANGE ALL | | 75 | 1875 | 4537 (30)| 00:00:01 | 1 | 5 |
|* 5 | TABLE ACCESS INMEMORY FULL | LINEORDER | 75 | 1875 | 4537 (30)| 00:00:01 | 1 | 5 |
| 6 | SORT AGGREGATE | | 1 | 8 | | | | |
| 7 | PARTITION RANGE ALL | | 33M| 254M| 4192 (24)| 00:00:01 | 1 | 5 |
|* 8 | TABLE ACCESS INMEMORY FULL| LINEORDER | 33M| 254M| 4192 (24)| 00:00:01 | 1 | 5 |
---------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - inmemory("LO_REVENUE"=)filter("LO_REVENUE"=)5 - inmemory(("LO_SHIPMODE" LIKE 'TRUCK%' AND "LO_DISCOUNT"<=5 AND "LO_DISCOUNT">=2 AND"LO_SUPPLYCOST"=))filter(("LO_SHIPMODE" LIKE 'TRUCK%' AND "LO_DISCOUNT"<=5 AND "LO_DISCOUNT">=2 AND"LO_SUPPLYCOST"=))8 - inmemory("LO_QUANTITY">10)filter("LO_QUANTITY">10)-- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 8
IM scan CUs columns accessed 388
IM scan CUs memcompress for query low 234
IM scan CUs pcode aggregation pushdown 81
IM scan CUs pruned 29
IM scan rows 125282823
IM scan rows pcode aggregated 33408482
IM scan rows projected 85
IM scan rows valid 109859292
IM scan segments minmax eligible 234
physical reads 2
session logical reads 946622
session logical reads - IM 946449
session pga memory 18286896
table scans (IM) 1515 rows selected.
即使有所有这些复杂的谓词,优化器还是选择了In-Memory查询,这表明对于大型扫描操作,这是最有效的方法。
实验小节:
在本实验中,您有机会通过针对超过 4100 万行的表(即 LINEORDER 表,该表驻留在 IM 列存储和缓冲区缓存 KEEP 池中)运行查询来尝试 Oracle 宣称的In-Memory性能。 从非常简单的聚合到具有多列和过滤谓词的更复杂查询,IM 列存储能够胜过缓冲区缓存查询。 请记住,这两组查询都完全在内存中执行,因此这是一个令人印象深刻的改进。
由于 Oracle 独特的内存中列格式允许我们只扫描我们需要的列并充分利用 SIMD 矢量处理,这些显着的性能改进是可能的。 我们还从新的内存存储索引中获得了一些帮助,这使我们能够跳过不必要的数据。 请记住,使用 IM 列存储,每列都有一个为您自动维护的存储索引。
实验 5:连接和聚合
到目前为止,我们一直专注于只扫描一个表的查询,即 LINEORDER 表。 让我们扩大考察的范围,包括连接和并行执行。 此部分执行一系列查询,这些查询以事实表LINEORDER 和一个或多个维度表之间的单个联接开始,最多可进行 5 个表联接。 查询将在缓冲区缓存和列存储中执行,以演示列存储可以提高查询性能的不同方式,而不仅仅是以列格式扫描数据的基本性能优势。
此实验的主要脚本执行序列如下,后面会详述:
@01_join_im.sql
@02_join_buffer.sql
@03_3join_im.sql
@04_3join_buffer.sql
@05_join_nl_im.sql
@06_vgb_im.sql
@07_novgb_im.sql
@08_vgb_buffer.sql
@09_novgb_buffer.sql
每次实验前,都需要执行以下:
. ~/.set-env-db.sh CDB1
进入joins-aggr目录,登录数据库:
cd /home/oracle/labs/inmemory/joins-aggr
sqlplus ssb/Ora_DB4U@localhost:1521/pdb1
调整显示:
set pages 9999
set lines 150
先看一个“What-if”查询:
SQL> @01_join_im.sql
-- 耗时
Elapsed: 00:00:00.04-- 执行计划
------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 4595 (100)| | | |
| 1 | SORT AGGREGATE | | 1 | 47 | | | | |
|* 2 | HASH JOIN | | 2085 | 97995 | 4595 (31)| 00:00:01 | | |
| 3 | JOIN FILTER CREATE | :BF0001 | 1 | 27 | 1 (0)| 00:00:01 | | |
| 4 | PART JOIN FILTER CREATE | :BF0000 | 1 | 27 | 1 (0)| 00:00:01 | | |
|* 5 | TABLE ACCESS INMEMORY FULL| DATE_DIM | 1 | 27 | 1 (0)| 00:00:01 | | |
| 6 | JOIN FILTER USE | :BF0001 | 3492K| 66M| 4575 (30)| 00:00:01 | | |
| 7 | PARTITION RANGE JOIN-FILTER| | 3492K| 66M| 4575 (30)| 00:00:01 |:BF0000|:BF0000|
|* 8 | TABLE ACCESS INMEMORY FULL| LINEORDER | 3492K| 66M| 4575 (30)| 00:00:01 |:BF0000|:BF0000|
------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("L"."LO_ORDERDATE"="D"."D_DATEKEY")5 - inmemory("D"."D_DATE"='December 24, 1996')filter("D"."D_DATE"='December 24, 1996')8 - inmemory(("L"."LO_DISCOUNT"<=3 AND "L"."LO_QUANTITY"<24 AND "L"."LO_DISCOUNT">=2 ANDSYS_OP_BLOOM_FILTER(:BF0001,"L"."LO_ORDERDATE")))filter(("L"."LO_DISCOUNT"<=3 AND "L"."LO_QUANTITY"<24 AND "L"."LO_DISCOUNT">=2 ANDSYS_OP_BLOOM_FILTER(:BF0001,"L"."LO_ORDERDATE")))-- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 7
IM scan CUs columns accessed 70
IM scan CUs memcompress for query low 18
IM scan CUs pcode aggregation pushdown 17
IM scan rows 9128918
IM scan rows pcode aggregated 2131
IM scan rows projected 17
IM scan rows valid 9128918
IM scan segments minmax eligible 18
session logical reads 69667
session logical reads - IM 68987
session pga memory 18745648
table scans (IM) 213 rows selected.
Database In-Memory 使用连接执行查询没有问题,实际上可以通过利用布隆过滤器来优化散列连接。 在执行计划中很容易识别布隆过滤器。 它们将出现在两个地方,创建时(即 JOIN FILTER CREATE)和应用时(即 JOIN FILTER USE)。 查看上面计划中的 ID 3 和 ID 6。 您还可以通过查看计划下的谓词信息来了解用于构建 Bloom 过滤器的连接条件。
您可能还注意到在第 4 行使用了另一个布隆过滤器。这不是 Database In-Memory 特性,而只是 Oracle 数据库优化对构成 LINEORDER 表的分区的访问。 这里的一个要点是,使用 Database In-Memory 并不妨碍使用其他 Oracle Database 特性。
在buffer cache中的执行,慢了20倍:
SQL> @02_join_buffer.sql
-- 耗时
Elapsed: 00:00:00.80-- 执行计划
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 87113 (100)| | | |
| 1 | SORT AGGREGATE | | 1 | 44 | | | | |
|* 2 | HASH JOIN | | 24932 | 1071K| 87113 (2)| 00:00:04 | | |
| 3 | PART JOIN FILTER CREATE | :BF0000 | 1 | 27 | 7 (0)| 00:00:01 | | |
|* 4 | TABLE ACCESS FULL | DATE_DIM | 1 | 27 | 7 (0)| 00:00:01 | | |
| 5 | PARTITION RANGE JOIN-FILTER| | 41M| 677M| 86876 (2)| 00:00:04 |:BF0000|:BF0000|
| 6 | TABLE ACCESS FULL | LINEORDER | 41M| 677M| 86876 (2)| 00:00:04 |:BF0000|:BF0000|
-----------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("L"."LO_ORDERDATE"="D"."D_DATEKEY")4 - filter("D"."D_DATE"='December 24, 1996')-- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 84
IM scan segments disk 2
session logical reads 69106
session pga memory 19269936
您可能会注意到我们添加了一个提示来指定 NO_INMEMORY。 这是告诉优化器不要使用 IM 列存储的简单方法。 您可能还会注意到还有一个 NO_VECTOR_TRANSFORM 提示。 启用 Database In-Memory 时可以使用矢量变换,我们将在本实验的后面部分介绍它的优点。 目前,我们已禁用它,以便更容易地将此执行计划与上一步中的执行计划进行比较。
更复杂的,3表的联结和聚合:
SQL>
-- 耗时
Elapsed: 00:00:00.23-- 执行计划
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 5280 (100)| | | |
| 1 | HASH GROUP BY | | 1000 | 77000 | 5280 (38)| 00:00:01 | | |
|* 2 | HASH JOIN | | 98430 | 7401K| 5275 (38)| 00:00:01 | | |
| 3 | JOIN FILTER CREATE | :BF0001 | 365 | 4380 | 1 (0)| 00:00:01 | | |
| 4 | PART JOIN FILTER CREATE | :BF0000 | 365 | 4380 | 1 (0)| 00:00:01 | | |
|* 5 | TABLE ACCESS INMEMORY FULL | DATE_DIM | 365 | 4380 | 1 (0)| 00:00:01 | | |
|* 6 | HASH JOIN | | 451K| 28M| 5272 (38)| 00:00:01 | | |
| 7 | JOIN FILTER CREATE | :BF0002 | 4102 | 73836 | 4 (25)| 00:00:01 | | |
|* 8 | TABLE ACCESS INMEMORY FULL | SUPPLIER | 4102 | 73836 | 4 (25)| 00:00:01 | | |
|* 9 | HASH JOIN | | 2216K| 99M| 5256 (38)| 00:00:01 | | |
| 10 | JOIN FILTER CREATE | :BF0003 | 31882 | 716K| 97 (27)| 00:00:01 | | |
|* 11 | TABLE ACCESS INMEMORY FULL | PART | 31882 | 716K| 97 (27)| 00:00:01 | | |
| 12 | JOIN FILTER USE | :BF0001 | 41M| 955M| 4928 (35)| 00:00:01 | | |
| 13 | JOIN FILTER USE | :BF0002 | 41M| 955M| 4928 (35)| 00:00:01 | | |
| 14 | JOIN FILTER USE | :BF0003 | 41M| 955M| 4928 (35)| 00:00:01 | | |
| 15 | PARTITION RANGE JOIN-FILTER| | 41M| 955M| 4928 (35)| 00:00:01 |:BF0000|:BF0000|
|* 16 | TABLE ACCESS INMEMORY FULL| LINEORDER | 41M| 955M| 4928 (35)| 00:00:01 |:BF0000|:BF0000|
----------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("L"."LO_ORDERDATE"="D"."D_DATEKEY")5 - inmemory("D"."D_YEAR"=1997)filter("D"."D_YEAR"=1997)6 - access("L"."LO_SUPPKEY"="S"."S_SUPPKEY")8 - inmemory("S"."S_REGION"='AMERICA')filter("S"."S_REGION"='AMERICA')9 - access("L"."LO_PARTKEY"="P"."P_PARTKEY")11 - inmemory("P"."P_CATEGORY"='MFGR#12')filter("P"."P_CATEGORY"='MFGR#12')16 - inmemory(SYS_OP_BLOOM_FILTER_LIST(SYS_OP_BLOOM_FILTER(:BF0003,"L"."LO_PARTKEY"),SYS_OP_BLOOM_FILTER(:BF0002,"L"."LO_SUPPKEY"),SYS_OP_BLOOM_FILTER(:BF0001,"L"."LO_ORDERDATE")))filter(SYS_OP_BLOOM_FILTER_LIST(SYS_OP_BLOOM_FILTER(:BF0003,"L"."LO_PARTKEY"),SYS_OP_BLOOM_FILTER(:BF0002,"L"."LO_SUPPKEY"),SYS_OP_BLOOM_FILTER(:BF0001,"L"."LO_ORDERDATE")))-- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 26
IM scan CUs columns accessed 78
IM scan CUs memcompress for query low 21
IM scan rows 9920979
IM scan rows projected 259319
IM scan rows valid 9920979
IM scan segments minmax eligible 21
session logical reads 76259
session logical reads - IM 75941
session pga memory 19466544
table scans (IM) 411 rows selected.
在此查询中,已创建三个 Bloom 过滤器并将其应用于 LINEORDER 表的扫描,一个用于连接 DATE_DIM 表,一个用于连接 PART 表,一个用于连接 SUPPLIER 表。当一个连接通常一次只涉及两个表时,Oracle 如何应用三个布隆过滤器?
这就是 Oracle 30 多年的数据库创新发挥作用的地方。通过将列存储嵌入到 Oracle 数据库中,我们可以利用已添加到数据库中的所有优化。在这种情况下,优化器已使用称为“swap_join_inputs”的优化从其典型的左深度树执行切换到右深度树执行计划。这对 IM 列存储意味着我们能够通过在扫描“事实”表中的必要列之前扫描三个“维度”表来生成多个布隆过滤器,这意味着我们能够在扫描时去除行而不是等待Join来执行它。
在buffer cache执行上一个查询,慢了4倍:
SQL>
-- 耗时
Elapsed: 00:00:01.00-- 执行计划
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 89164 (100)| | | |
| 1 | HASH GROUP BY | | 1000 | 77000 | 89164 (2)| 00:00:04 | | |
|* 2 | HASH JOIN | | 98430 | 7401K| 89159 (2)| 00:00:04 | | |
| 3 | PART JOIN FILTER CREATE | :BF0000 | 365 | 4380 | 7 (0)| 00:00:01 | | |
|* 4 | TABLE ACCESS FULL | DATE_DIM | 365 | 4380 | 7 (0)| 00:00:01 | | |
|* 5 | HASH JOIN | | 451K| 28M| 89149 (2)| 00:00:04 | | |
|* 6 | TABLE ACCESS FULL | SUPPLIER | 4102 | 73836 | 70 (2)| 00:00:01 | | |
|* 7 | HASH JOIN | | 2216K| 99M| 89067 (2)| 00:00:04 | | |
|* 8 | TABLE ACCESS FULL | PART | 31882 | 716K| 1915 (2)| 00:00:01 | | |
| 9 | PARTITION RANGE JOIN-FILTER| | 41M| 955M| 86922 (2)| 00:00:04 |:BF0000|:BF0000|
| 10 | TABLE ACCESS FULL | LINEORDER | 41M| 955M| 86922 (2)| 00:00:04 |:BF0000|:BF0000|
-------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("L"."LO_ORDERDATE"="D"."D_DATEKEY")4 - filter("D"."D_YEAR"=1997)5 - access("L"."LO_SUPPKEY"="S"."S_SUPPKEY")6 - filter("S"."S_REGION"='AMERICA')7 - access("L"."LO_PARTKEY"="P"."P_PARTKEY")8 - filter("P"."P_CATEGORY"='MFGR#12')-- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 126
IM scan segments disk 4
session logical reads 80154
session pga memory 20777264
到目前为止,我们只看到了与内存查询一起使用的哈希连接。 虽然哈希联接确实是对 Database In-Memory 的进一步优化,并且它能够使用 Bloom 过滤器将联接有效地执行为扫描和过滤操作,但是嵌套循环联接呢? Database In-Memory 是否可以使用嵌套循环连接? 也许一个表不在内存中,或者索引访问的成本会更低。 让我们看看它是如何工作的。此查询中,我们通过提示启用了隐藏的索引。
SQL> 05_join_nl_im.sql
-- 耗时
Elapsed: 00:00:00.06-- 执行计划
--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 6134 (100)| | | |
| 1 | SORT AGGREGATE | | 1 | 44 | | | | |
| 2 | NESTED LOOPS | | 24932 | 1071K| 6134 (1)| 00:00:01 | | |
| 3 | NESTED LOOPS | | 24932 | 1071K| 6134 (1)| 00:00:01 | | |
|* 4 | TABLE ACCESS INMEMORY FULL | DATE_DIM | 1 | 27 | 1 (0)| 00:00:01 | | |
| 5 | PARTITION RANGE ITERATOR | | 24932 | | 65 (0)| 00:00:01 | KEY | KEY |
|* 6 | INDEX RANGE SCAN | LINEORDER_I1 | 24932 | | 65 (0)| 00:00:01 | KEY | KEY |
| 7 | TABLE ACCESS BY LOCAL INDEX ROWID| LINEORDER | 24932 | 413K| 6133 (1)| 00:00:01 | 1 | 1 |
--------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------4 - inmemory("D"."D_DATE"='December 24, 1996')filter("D"."D_DATE"='December 24, 1996')6 - access("L"."LO_ORDERDATE"="D"."D_DATEKEY")Note
------ this is an adaptive plan
请注意,我们已经告诉优化器它可以使用不可见的索引,并且我们添加了一个可以在 LINEORDER 表上使用的索引提示。 这导致优化器选择执行嵌套循环连接,首先访问内存中的 DATE_DIM 表,然后通过索引访问 LINEORDER 表。 在此示例中,访问 IM 列存储中的 LINEORDER 表的成本较低,但我们想向您展示优化器在使用内存时可以选择不同的连接类型。 如果您喜欢冒险,您可以编辑脚本并删除索引提示。 不用担心,这是您自己的环境,不会影响其他人。 如果您随后再次运行查询,您可以比较通过使用嵌套循环连接的索引访问数据的成本。 要记住的是优化器能够选择成本最低的方法来运行查询,无论是否访问内存中的对象。
确实,本例使用Nested Loop联结确实比哈希Join快些。
现在让我们将注意力转向更多 OLAP 风格的“What-if”查询。
Oracle 引入了一种新的优化器转换,称为向量转换。这也称为 In-Memory Aggregation,并产生一个新的 group by 方法,称为 Vector Group By。这种转换是一个两部分的过程,与星型转换的过程没有什么不同。
原理就不翻译了:
First, the dimension tables are scanned and any WHERE clause predicates are applied. A new data structure called a key vector is created based on the results of these scans. The key vector is similar to a Bloom filter as it allows the join predicates to be applied as additional filter predicates during the scan of the fact table, but it also enables us to conduct the group by or aggregation during the scan of the fact table instead of having to do it afterwards.
The second part of the execution plan sees the results of the fact table scan being joined back to the temporary tables created as part of the scan of the dimension tables, that is defined by the lines that start with LOAD AS SELECT. These temporary tables contain the payload columns (columns needed in the select list) from the dimension table(s). In Release 12.2 and above these tables are now pure in-memory tables as evidenced by the addition of the (CURSOR DURATION MEMORY) phrase that is appended to the LOAD AS SELECT phrases. The combination of these two features dramatically improves the efficiency of a multiple table join with complex aggregations. Both features are visible in the execution plan of our queries.
来看下Vector Group By的效果:
SQL> @06_vgb_im.sql
-- 耗时
Elapsed: 00:00:00.67-- 执行计划
--------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 5619 (100)| | | |
| 1 | TEMP TABLE TRANSFORMATION | | | | | | | |
| 2 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D663D_53FD65 | | | | | | |
| 3 | HASH GROUP BY | | 7 | 112 | 2 (50)| 00:00:01 | | |
| 4 | KEY VECTOR CREATE BUFFERED | :KV0000 | 7 | 112 | 1 (0)| 00:00:01 | | |
| 5 | TABLE ACCESS INMEMORY FULL | DATE_DIM | 2556 | 30672 | 1 (0)| 00:00:01 | | |
| 6 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D663A_53FD65 | | | | | | |
| 7 | HASH GROUP BY | | 1 | 9 | 120 (41)| 00:00:01 | | |
| 8 | KEY VECTOR CREATE BUFFERED | :KV0001 | 1 | 9 | 80 (12)| 00:00:01 | | |
| 9 | TABLE ACCESS INMEMORY FULL | PART | 800K| 3906K| 77 (8)| 00:00:01 | | |
| 10 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D663B_53FD65 | | | | | | |
| 11 | HASH GROUP BY | | 1 | 22 | 5 (40)| 00:00:01 | | |
| 12 | KEY VECTOR CREATE BUFFERED | :KV0002 | 1 | 22 | 4 (25)| 00:00:01 | | |
|* 13 | TABLE ACCESS INMEMORY FULL | SUPPLIER | 4102 | 73836 | 4 (25)| 00:00:01 | | |
| 14 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D663C_53FD65 | | | | | | |
| 15 | HASH GROUP BY | | 25 | 950 | 45 (32)| 00:00:01 | | |
| 16 | KEY VECTOR CREATE BUFFERED | :KV0003 | 25 | 950 | 41 (25)| 00:00:01 | | |
|* 17 | TABLE ACCESS INMEMORY FULL | CUSTOMER | 59761 | 1984K| 41 (25)| 00:00:01 | | |
| 18 | SORT GROUP BY | | 62 | 6510 | 5448 (41)| 00:00:01 | | |
|* 19 | HASH JOIN | | 62 | 6510 | 5447 (41)| 00:00:01 | | |
|* 20 | HASH JOIN | | 62 | 4712 | 5445 (41)| 00:00:01 | | |
| 21 | MERGE JOIN CARTESIAN | | 7 | 329 | 6 (0)| 00:00:01 | | |
| 22 | MERGE JOIN CARTESIAN | | 1 | 31 | 4 (0)| 00:00:01 | | |
| 23 | TABLE ACCESS FULL | SYS_TEMP_0FD9D663A_53FD65 | 1 | 9 | 2 (0)| 00:00:01 | | |
| 24 | BUFFER SORT | | 1 | 22 | 2 (0)| 00:00:01 | | |
| 25 | TABLE ACCESS FULL | SYS_TEMP_0FD9D663B_53FD65 | 1 | 22 | 2 (0)| 00:00:01 | | |
| 26 | BUFFER SORT | | 7 | 112 | 4 (0)| 00:00:01 | | |
| 27 | TABLE ACCESS FULL | SYS_TEMP_0FD9D663D_53FD65 | 7 | 112 | 2 (0)| 00:00:01 | | |
| 28 | VIEW | VW_VT_80F21617 | 62 | 1798 | 5439 (41)| 00:00:01 | | |
| 29 | VECTOR GROUP BY | | 62 | 3100 | 5439 (41)| 00:00:01 | | |
| 30 | HASH GROUP BY | | 62 | 3100 | 5439 (41)| 00:00:01 | | |
| 31 | KEY VECTOR USE | :KV0000 | 2535K| 120M| 5437 (41)| 00:00:01 | | |
| 32 | KEY VECTOR USE | :KV0001 | 2535K| 111M| 5436 (41)| 00:00:01 | | |
| 33 | KEY VECTOR USE | :KV0003 | 2535K| 101M| 5436 (41)| 00:00:01 | | |
| 34 | KEY VECTOR USE | :KV0002 | 8510K| 308M| 5436 (41)| 00:00:01 | | |
| 35 | PARTITION RANGE ITERATOR | | 41M| 1354M| 5434 (41)| 00:00:01 |:KV0000|:KV0000|
|* 36 | TABLE ACCESS INMEMORY FULL | LINEORDER | 41M| 1354M| 5434 (41)| 00:00:01 |:KV0000|:KV0000|
| 37 | TABLE ACCESS FULL | SYS_TEMP_0FD9D663C_53FD65 | 25 | 725 | 2 (0)| 00:00:01 | | |
--------------------------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------13 - inmemory("S"."S_REGION"='AMERICA')filter("S"."S_REGION"='AMERICA')17 - inmemory("C"."C_REGION"='AMERICA')filter("C"."C_REGION"='AMERICA')19 - access("ITEM_14"=INTERNAL_FUNCTION("C0"))20 - access("ITEM_12"=INTERNAL_FUNCTION("C0") AND "ITEM_13"=INTERNAL_FUNCTION("C0") AND "ITEM_15"=INTERNAL_FUNCTION("C0"))36 - inmemory((SYS_OP_KEY_VECTOR_FILTER("L"."LO_SUPPKEY",:KV0002) AND SYS_OP_KEY_VECTOR_FILTER("L"."LO_CUSTKEY",:KV0003)AND SYS_OP_KEY_VECTOR_FILTER("L"."LO_PARTKEY",:KV0001) AND SYS_OP_KEY_VECTOR_FILTER("L"."LO_ORDERDATE",:KV0000)))filter((SYS_OP_KEY_VECTOR_FILTER("L"."LO_SUPPKEY",:KV0002) AND SYS_OP_KEY_VECTOR_FILTER("L"."LO_CUSTKEY",:KV0003) ANDSYS_OP_KEY_VECTOR_FILTER("L"."LO_PARTKEY",:KV0001) AND SYS_OP_KEY_VECTOR_FILTER("L"."LO_ORDERDATE",:KV0000)))Note
------ vector transformation used for this statement
我们的查询现在更加复杂,如果您仔细查看执行计划,您将看到:KV000n 结构的创建和使用,这些结构是关键向量以及 Vector Group By 操作。
如果没有Vector Group By,性能如何?优化器选择了布隆过滤器,性能慢了2倍。
SQL>
-- 耗时
Elapsed: 00:00:01.40-- 执行计划
------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | | 44344 (100)| | | |
| 1 | SORT GROUP BY | | 124 | 12772 | | 44344 (7)| 00:00:02 | | |
|* 2 | HASH JOIN | | 2535K| 249M| | 44209 (6)| 00:00:02 | | |
| 3 | PART JOIN FILTER CREATE | :BF0000 | 2556 | 30672 | | 1 (0)| 00:00:01 | | |
| 4 | TABLE ACCESS INMEMORY FULL | DATE_DIM | 2556 | 30672 | | 1 (0)| 00:00:01 | | |
|* 5 | HASH JOIN | | 2535K| 220M| 12M| 44194 (6)| 00:00:02 | | |
| 6 | TABLE ACCESS INMEMORY FULL | PART | 800K| 3906K| | 77 (8)| 00:00:01 | | |
|* 7 | HASH JOIN | | 2535K| 207M| 2688K| 31688 (9)| 00:00:02 | | |
| 8 | JOIN FILTER CREATE | :BF0001 | 59761 | 1984K| | 41 (25)| 00:00:01 | | |
|* 9 | TABLE ACCESS INMEMORY FULL | CUSTOMER | 59761 | 1984K| | 41 (25)| 00:00:01 | | |
|* 10 | HASH JOIN | | 8510K| 422M| | 5668 (44)| 00:00:01 | | |
| 11 | JOIN FILTER CREATE | :BF0002 | 4102 | 73836 | | 4 (25)| 00:00:01 | | |
|* 12 | TABLE ACCESS INMEMORY FULL | SUPPLIER | 4102 | 73836 | | 4 (25)| 00:00:01 | | |
| 13 | JOIN FILTER USE | :BF0001 | 41M| 1354M| | 5434 (41)| 00:00:01 | | |
| 14 | JOIN FILTER USE | :BF0002 | 41M| 1354M| | 5434 (41)| 00:00:01 | | |
| 15 | PARTITION RANGE JOIN-FILTER| | 41M| 1354M| | 5434 (41)| 00:00:01 |:BF0000|:BF0000|
|* 16 | TABLE ACCESS INMEMORY FULL| LINEORDER | 41M| 1354M| | 5434 (41)| 00:00:01 |:BF0000|:BF0000|
------------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("L"."LO_ORDERDATE"="D"."D_DATEKEY")5 - access("L"."LO_PARTKEY"="P"."P_PARTKEY")7 - access("L"."LO_CUSTKEY"="C"."C_CUSTKEY")9 - inmemory("C"."C_REGION"='AMERICA')filter("C"."C_REGION"='AMERICA')10 - access("L"."LO_SUPPKEY"="S"."S_SUPPKEY")12 - inmemory("S"."S_REGION"='AMERICA')filter("S"."S_REGION"='AMERICA')16 - inmemory(SYS_OP_BLOOM_FILTER_LIST(SYS_OP_BLOOM_FILTER(:BF0002,"L"."LO_SUPPKEY"),SYS_OP_BLOOM_FILTER(:BF0001,"L"."LO_CUSTKEY")))filter(SYS_OP_BLOOM_FILTER_LIST(SYS_OP_BLOOM_FILTER(:BF0002,"L"."LO_SUPPKEY"),SYS_OP_BLOOM_FILTER(:BF0001,"L"."LO_CUSTKEY")))
在这个实验室中,我们的表非常小,但随着表的大小增加,性能差异通常会大得多。 这就是为什么我们说您通常可以期望使用内存聚合至少可以提高 3-8 倍的性能。
在没有Database In-Memory时,向量转换也是可以用的,不过慢了7倍。
SQL> @08_vgb_buffer.sql
-- 耗时
Elapsed: 00:00:04.76-- 执行计划
--------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 89852 (100)| | | |
| 1 | TEMP TABLE TRANSFORMATION | | | | | | | |
| 2 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D6647_53FD65 | | | | | | |
| 3 | HASH GROUP BY | | 7 | 112 | 8 (13)| 00:00:01 | | |
| 4 | KEY VECTOR CREATE BUFFERED | :KV0000 | 7 | 112 | 7 (0)| 00:00:01 | | |
| 5 | TABLE ACCESS FULL | DATE_DIM | 2556 | 30672 | 7 (0)| 00:00:01 | | |
| 6 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D6644_53FD65 | | | | | | |
| 7 | HASH GROUP BY | | 1 | 9 | 1944 (3)| 00:00:01 | | |
| 8 | KEY VECTOR CREATE BUFFERED | :KV0001 | 1 | 9 | 1904 (1)| 00:00:01 | | |
| 9 | TABLE ACCESS FULL | PART | 800K| 3906K| 1901 (1)| 00:00:01 | | |
| 10 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D6645_53FD65 | | | | | | |
| 11 | HASH GROUP BY | | 1 | 22 | 71 (3)| 00:00:01 | | |
| 12 | KEY VECTOR CREATE BUFFERED | :KV0002 | 1 | 22 | 70 (2)| 00:00:01 | | |
|* 13 | TABLE ACCESS FULL | SUPPLIER | 4102 | 73836 | 70 (2)| 00:00:01 | | |
| 14 | LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D6646_53FD65 | | | | | | |
| 15 | HASH GROUP BY | | 25 | 950 | 848 (2)| 00:00:01 | | |
| 16 | KEY VECTOR CREATE BUFFERED | :KV0003 | 25 | 950 | 845 (2)| 00:00:01 | | |
|* 17 | TABLE ACCESS FULL | CUSTOMER | 59761 | 1984K| 844 (2)| 00:00:01 | | |
| 18 | SORT GROUP BY | | 62 | 6510 | 86982 (2)| 00:00:04 | | |
|* 19 | HASH JOIN | | 62 | 6510 | 86981 (2)| 00:00:04 | | |
|* 20 | HASH JOIN | | 62 | 4712 | 86979 (2)| 00:00:04 | | |
| 21 | MERGE JOIN CARTESIAN | | 7 | 329 | 6 (0)| 00:00:01 | | |
| 22 | MERGE JOIN CARTESIAN | | 1 | 31 | 4 (0)| 00:00:01 | | |
| 23 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6644_53FD65 | 1 | 9 | 2 (0)| 00:00:01 | | |
| 24 | BUFFER SORT | | 1 | 22 | 2 (0)| 00:00:01 | | |
| 25 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6645_53FD65 | 1 | 22 | 2 (0)| 00:00:01 | | |
| 26 | BUFFER SORT | | 7 | 112 | 4 (0)| 00:00:01 | | |
| 27 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6647_53FD65 | 7 | 112 | 2 (0)| 00:00:01 | | |
| 28 | VIEW | VW_VT_80F21617 | 62 | 1798 | 86973 (2)| 00:00:04 | | |
| 29 | VECTOR GROUP BY | | 62 | 3100 | 86973 (2)| 00:00:04 | | |
| 30 | HASH GROUP BY | | 62 | 3100 | 86973 (2)| 00:00:04 | | |
| 31 | KEY VECTOR USE | :KV0000 | 2535K| 120M| 86970 (2)| 00:00:04 | | |
| 32 | KEY VECTOR USE | :KV0001 | 2535K| 111M| 86970 (2)| 00:00:04 | | |
| 33 | KEY VECTOR USE | :KV0003 | 2535K| 101M| 86970 (2)| 00:00:04 | | |
| 34 | KEY VECTOR USE | :KV0002 | 8510K| 308M| 86969 (2)| 00:00:04 | | |
| 35 | PARTITION RANGE ITERATOR | | 41M| 1354M| 86968 (2)| 00:00:04 |:KV0000|:KV0000|
|* 36 | TABLE ACCESS FULL | LINEORDER | 41M| 1354M| 86968 (2)| 00:00:04 |:KV0000|:KV0000|
| 37 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6646_53FD65 | 25 | 725 | 2 (0)| 00:00:01 | | |
--------------------------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------13 - filter("S"."S_REGION"='AMERICA')17 - filter("C"."C_REGION"='AMERICA')19 - access("ITEM_14"=INTERNAL_FUNCTION("C0"))20 - access("ITEM_12"=INTERNAL_FUNCTION("C0") AND "ITEM_13"=INTERNAL_FUNCTION("C0") AND "ITEM_15"=INTERNAL_FUNCTION("C0"))36 - filter((SYS_OP_KEY_VECTOR_FILTER("L"."LO_SUPPKEY",:KV0002) AND SYS_OP_KEY_VECTOR_FILTER("L"."LO_CUSTKEY",:KV0003) ANDSYS_OP_KEY_VECTOR_FILTER("L"."LO_PARTKEY",:KV0001) AND SYS_OP_KEY_VECTOR_FILTER("L"."LO_ORDERDATE",:KV0000)))Note
------ vector transformation used for this statement
在buffer cache中,如果禁用向量转换呢?慢了15倍。
SQL> @09_novgb_buffer.sql
-- 耗时
Elapsed: 00:00:10.19-- 执行计划
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | | 128K(100)| | | |
| 1 | SORT GROUP BY | | 124 | 12772 | | 128K (2)| 00:00:06 | | |
|* 2 | HASH JOIN | | 2535K| 249M| | 128K (2)| 00:00:06 | | |
| 3 | PART JOIN FILTER CREATE | :BF0000 | 2556 | 30672 | | 7 (0)| 00:00:01 | | |
| 4 | TABLE ACCESS FULL | DATE_DIM | 2556 | 30672 | | 7 (0)| 00:00:01 | | |
|* 5 | HASH JOIN | | 2535K| 220M| 12M| 128K (2)| 00:00:06 | | |
| 6 | TABLE ACCESS FULL | PART | 800K| 3906K| | 1901 (1)| 00:00:01 | | |
|* 7 | HASH JOIN | | 2535K| 207M| 2688K| 114K (2)| 00:00:05 | | |
|* 8 | TABLE ACCESS FULL | CUSTOMER | 59761 | 1984K| | 844 (2)| 00:00:01 | | |
|* 9 | HASH JOIN | | 8510K| 422M| | 87268 (2)| 00:00:04 | | |
|* 10 | TABLE ACCESS FULL | SUPPLIER | 4102 | 73836 | | 70 (2)| 00:00:01 | | |
| 11 | PARTITION RANGE JOIN-FILTER| | 41M| 1354M| | 86968 (2)| 00:00:04 |:BF0000|:BF0000|
| 12 | TABLE ACCESS FULL | LINEORDER | 41M| 1354M| | 86968 (2)| 00:00:04 |:BF0000|:BF0000|
----------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("L"."LO_ORDERDATE"="D"."D_DATEKEY")5 - access("L"."LO_PARTKEY"="P"."P_PARTKEY")7 - access("L"."LO_CUSTKEY"="C"."C_CUSTKEY")8 - filter("C"."C_REGION"='AMERICA')9 - access("L"."LO_SUPPKEY"="S"."S_SUPPKEY")10 - filter("S"."S_REGION"='AMERICA')
小节:
本节主要介绍了布隆过滤器和向量转换。
实验 6:JSON 和 In-Memory 列存储
简介
Oracle 数据库在 12.1 中引入了对 JSON 数据的支持,并且在 Oracle 数据库 12c 第 2 版 (12.2) 中添加了对可以填充到 IM 列存储中的二进制 JSON 格式的支持。 这使 Oracle 数据库能够利用 DBIM 功能并允许直接对 JSON 数据进行高性能分析。 事实上,从 Oracle Database 21c 开始,现在支持 JSON 数据类型,并且也可以在 IM 列存储中填充。 请注意,要在 IM 列存储中填充的 JSON 文档必须小于 32,767 字节。 如果它大于 32,767 字节,则将在没有内存优化的情况下对其进行处理。
在本实验中,您将了解 21c 之前的 IM 列存储如何支持 JSON 数据,以及 21c 和新的 JSON 数据类型如何支持它。
任务 1:验证在 IM 列存储中填充 JSON 数据的先决条件
此实验的主要脚本执行序列如下,后面会详述:
@01_disable_tables.sql
@02_json_prereq.sql
@03_j_purchaseorder.sql
@04_enable_json.sql
@05_json_query.sql
@06_json_pop.sql
@07_im_populated.sql
@08_ime_usage.sql
@09_json_query.sql
@10_json_purchaseorder.sql
@11_json_pop.sql
@12_im_populated.sql
@13_json_query.sql
@14_json_cleanup.sql
要在 IM 列存储中填充 JSON 数据,必须设置几个数据库先决条件。 下面列出了这些先决条件,所有这些都已针对您的 LiveLabs 环境完成:
- 数据库兼容性设置为 12.2.0 或更高版本
- MAX_STRING_SIZE 设置为“EXTENDED”
- INMEMORY_EXPRESSIONS_USAGE 设置为 ‘STATIC_ONLY’ 或 ‘ENABLE’
- INMEMORY_VIRTUAL_COLUMNS 设置为“启用”
JSON 数据列在 21c 之前必须具有“IS JSON”检查约束。 在 21c 中,JSON 数据类型的列不需要检查约束,但 compatible 参数必须至少设置为 20。
实验前,需要执行以下:
. ~/.set-env-db.sh CDB1
进入json目录,登录数据库:
cd /home/oracle/labs/inmemory/json
sqlplus ssb/Ora_DB4U@localhost:1521/pdb1
调整显示:
set pages 9999
set lines 150
由于本实验用了新的测试表,因此需要将之前的表从内存中清出:
SQL> @01_disable_tables.sql
这段PL/SQL代码值得学习,分别考虑了普通表和分区表:
set serveroutput on;
declarev_ddl varchar2(1000);
beginfor tab_cursor in (select owner, table_namefrom dba_tableswhere owner not in ('AUDSYS','SYS')and inmemory = 'ENABLED')loopv_ddl := 'alter table '||tab_cursor.owner||'.'||tab_cursor.table_name||' no inmemory';dbms_output.put_line(v_ddl);execute immediate v_ddl;end loop;--for part_cursor in (select table_owner, table_name, partition_namefrom dba_tab_partitionswhere table_owner not in ('AUDSYS','SYS')and inmemory = 'ENABLED')loopv_ddl := 'alter table '||part_cursor.table_owner||'.'||part_cursor.table_name||' modify partition '||part_cursor.partition_name||' no inmemory';dbms_output.put_line(v_ddl);execute immediate v_ddl;end loop;
end;
/
确认先决条件:
SQL> @02_json_prereq.sql
Connected.NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
compatible string 21.0.0
noncdb_compatible boolean FALSENAME TYPE VALUE
------------------------------------ ----------- ------------------------------
max_string_size string EXTENDEDNAME TYPE VALUE
------------------------------------ ----------- ------------------------------
inmemory_expressions_usage string ENABLENAME TYPE VALUE
------------------------------------ ----------- ------------------------------
inmemory_virtual_columns string ENABLE
任务 2:在 21c 之前填充 IM 列存储中的 JSON 数据
首先,我们将显示 J_PURCHASEORDER 表。 这是我们将用于示例的表(其实也是Oracle标准的示例表),与 19c JSON 开发人员指南中创建和使用的表相同。
SQL> @03_j_purchaseorder.sql
Connected.Name Null? Type----------------------------------------- -------- ----------------------------ID NOT NULL VARCHAR2(32)DATE_LOADED TIMESTAMP(6) WITH TIME ZONEPO_DOCUMENT VARCHAR2(32767)TABLE_NAME COLUMN_NAME DATA_TYPE DATA_LENGTH DATA_DEFAULT
-------------------- ------------------------------ ------------------------------ ----------- ------------------------------
J_PURCHASEORDER ID VARCHAR2 32
J_PURCHASEORDER DATE_LOADED TIMESTAMP(6) WITH TIME ZONE 13
J_PURCHASEORDER PO_DOCUMENT VARCHAR2 32767TABLE_NAME CONSTRAINT_NAME C SEARCH_CONDITION
-------------------- -------------------- - ------------------------------
J_PURCHASEORDER SYS_C008287 C "ID" IS NOT NULL
J_PURCHASEORDER SYS_C008289 P
PO_DOCUMENT列存放的是JSON数据,目前列上还没有关于JSON的约束。
下一步将在 PO_DOCUMENT 列上定义检查约束,以确保 JSON 格式正确并启用 JSON 数据的内存优化。因为有数据(640000行),alter table会慢一点。
SQL> @04_enable_json.sql
Connected.
SQL>
SQL> alter table j_purchaseorder add constraint ensure_json check (po_document is json);Table altered.SQL>
SQL> set echo offTABLE_NAME COLUMN_NAME DATA_TYPE DATA_LENGTH DATA_DEFAULT
-------------------- ------------------------------ ------------------------------ ----------- ------------------------------
J_PURCHASEORDER ID VARCHAR2 32
J_PURCHASEORDER DATE_LOADED TIMESTAMP(6) WITH TIME ZONE 13
J_PURCHASEORDER PO_DOCUMENT VARCHAR2 32767
J_PURCHASEORDER SYS_IME_OSON_00242D59FB994F94B RAW 32767 OSON("PO_DOCUMENT" FORMAT JSONF9AEE8C6586313E , 'ime' RETURNING RAW(32767)NULL ON ERROR)TABLE_NAME CONSTRAINT_NAME C SEARCH_CONDITION
-------------------- -------------------- - ------------------------------
J_PURCHASEORDER SYS_C008287 C "ID" IS NOT NULL
J_PURCHASEORDER ENSURE_JSON C po_document is json
J_PURCHASEORDER SYS_C008289 P
请注意,我们不仅在 PO_DOCUMENT 列上创建了检查约束,而且还导致创建了一个以名称 SYS_IME_OSON 开头的新虚拟列。 Oracle 数据库创建了 PO_DOCUMENT 列的特殊二进制版本(这意味着需要额外的存储空间)。
开始JSON查询,此时表还没有发布:
SQL> @05_json_query.sql
-- 耗时
Elapsed: 00:00:12.78-- 执行计划
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | | 2968M(100)| |
| 1 | SORT ORDER BY | | 10000 | 18M| 9970G| 2968M (1)| 32:12:43 |
| 2 | HASH GROUP BY | | 10000 | 18M| 9970G| 2968M (1)| 32:12:43 |
| 3 | NESTED LOOPS | | 5227M| 9357G| | 17M (1)| 00:11:22 |
|* 4 | TABLE ACCESS FULL | J_PURCHASEORDER | 640K| 1170M| | 26402 (1)| 00:00:02 |
| 5 | JSONTABLE EVALUATION | | | | | | |
----------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------4 - filter(INTERNAL_FUNCTION("PO_DOCUMENT" /*+ LOB_BY_VALUE */ ))-- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 1288
physical reads 96829
session logical reads 100861
session pga memory 19401008
发布表:
SQL> @@06_json_pop.sql
Connected.
SQL>
SQL> alter table j_purchaseorder inmemory;Table altered.SQL>
SQL> exec dbms_inmemory.populate(USER, 'J_PURCHASEORDER');PL/SQL procedure successfully completed.SQL>
SQL> set echo off
确认发布:
SQL> @@07_im_populated.sql
Connected.
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 order by owner, segment_name, partition_name;In-Memory Bytes
OWNER SEGMENT_NAME PARTITION_NAME POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB J_PURCHASEORDER COMPLETED 793,198,592 1,056,702,464 0SQL>
SQL> set echo off
注意到消耗的内存比磁盘空间大。
由于创建了虚拟列,它将作为内存中表达式 (IME) 存储在 IM 列存储中。 让我们检查一下二进制 JSON 数据需要多少额外空间。
SQL> @08_ime_usage.sql
Connected.
SQL>
SQL> -- This query displays what objects are in the In-Memory Column Store
SQL>
SQL> select2 o.owner,3 o.object_name,4 o.subobject_name as partition_name,5 i.column_name,6 count(*) t_imeu,7 sum(i.length)/1024/1024 space8 from9 v$im_imecol_cu i,10 dba_objects o11 where12 i.objd = o.object_id13 group by14 o.owner,15 o.object_name,16 o.subobject_name,17 i.column_name;Partition Column Total Used
Owner Object Name Name IMEUs Space(MB)
---------- -------------------- -------------------- --------------- ------- ------------
SSB J_PURCHASEORDER SYS_IME_OSON_00 11 83242D59FB994F94BF9AEE8C6586313ESQL>
SQL> set echo off
空间不大,但它确实需要 IM 列存储中的一些额外空间,以便存储内存中优化的 JSON 数据。
再次运行查询,快了2.6倍:
SQL> @09_json_query.sql
-- 耗时
Elapsed: 00:00:04.88-- 执行计划
---------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | | 2968M(100)| |
| 1 | SORT ORDER BY | | 10000 | 18M| 9970G| 2968M (1)| 32:12:42 |
| 2 | HASH GROUP BY | | 10000 | 18M| 9970G| 2968M (1)| 32:12:42 |
| 3 | NESTED LOOPS | | 5227M| 9357G| | 17M (1)| 00:11:21 |
|* 4 | TABLE ACCESS INMEMORY FULL| J_PURCHASEORDER | 640K| 1170M| | 986 (1)| 00:00:01 |
| 5 | JSONTABLE EVALUATION | | | | | | |
---------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------4 - filter(INTERNAL_FUNCTION("PO_DOCUMENT" /*+ LOB_BY_VALUE */ ))-- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 491
IM scan CUs columns accessed 11
IM scan CUs memcompress for query low 11
IM scan EU rows 640000
IM scan EUs columns accessed 11
IM scan EUs memcompress for query low 11
IM scan rows 640000
IM scan rows pcode aggregated 640000
IM scan rows projected 639999
IM scan rows valid 640000
session logical reads 96919
session logical reads - IM 96826
session pga memory 18024752
table scans (IM) 114 rows selected.
这里有几点需要注意。 首先是查询运行了大约一半的时间。 这是一个相当不错的加速。 二是看统计数据。 请注意,现在有“IM scan EU”统计信息。 这是因为二进制 JSON 数据利用了另一个名为 In-Memory Expressions 的 Database In-Memory 功能。
任务 3:使用 21c 中的 JSON 数据类型填充 IM 列中的 JSON 数据
现在让我们切换到一个将 PO_DOCUMENT 列定义为 JSON 数据类型的新表JSON_PURCHASEORDER(之前的表为J_PURCHASEORDER,两个表都是640000行)。 JSON数据类型是 Oracle Database 21c 中的新功能。
SQL> @10_json_purchaseorder.sql
Connected.Column
TABLE_NAME Name DATA_TYPE DATA_LENGTH DATA_DEFAULT
-------------------- ------------------------------ ------------------------------ ----------- ------------------------------
JSON_PURCHASEORDER ID VARCHAR2 32
JSON_PURCHASEORDER DATE_LOADED TIMESTAMP(6) WITH TIME ZONE 13
JSON_PURCHASEORDER PO_DOCUMENT JSON 8200
JSON_PURCHASEORDER SYS_IME_OSON_9BCF95B616674FF9B RAW 32767 OSON("PO_DOCUMENT" FORMAT OSONFE78D6675051BFE , 'ime' RETURNING RAW(32767)NULL ON ERROR)TABLE_NAME CONSTRAINT_NAME C SEARCH_CONDITION
-------------------- -------------------- - ------------------------------
JSON_PURCHASEORDER SYS_C008286 C "ID" IS NOT NULL
JSON_PURCHASEORDER SYS_C008288 P
对于JSON数据类型,我们无需再建立约束。
发布:
SQL> @11_json_pop.sql
Connected.
SQL>
SQL> alter table j_purchaseorder no inmemory;Table altered.SQL>
SQL> alter table json_purchaseorder inmemory;Table altered.SQL>
SQL> exec dbms_inmemory.populate(USER, 'JSON_PURCHASEORDER');PL/SQL procedure successfully completed.SQL>
SQL> set echo off
确认已发布:
SQL> @12_im_populated.sql
Connected.
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 order by inmemory_size;Partition In-Memory Bytes
Owner SEGMENT_NAME Name POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB JSON_PURCHASEORDER COMPLETED 691,912,704 790,298,624 0SQL>
SQL> set echo off
虽然内存占用仍比磁盘多,但内存空间和磁盘空间相比21c之前的JSON列,已经小一些了。
内存中的查询:
SQL> @13_json_query.sql
-- 耗时
Elapsed: 00:00:04.94 -- 执行计划
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 18M(100)| |
| 1 | SORT ORDER BY | | 1 | 851 | 18M (6)| 00:11:53 |
| 2 | HASH GROUP BY | | 1 | 851 | 18M (6)| 00:11:53 |
| 3 | NESTED LOOPS | | 5227M| 4143G| 17M (1)| 00:11:21 |
| 4 | TABLE ACCESS INMEMORY FULL| JSON_PURCHASEORDER | 640K| 516M| 862 (1)| 00:00:01 |
| 5 | JSONTABLE EVALUATION | | | | | |
------------------------------------------------------------------------------------------------------ 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 495
IM scan CUs columns accessed 10
IM scan CUs memcompress for query low 10
IM scan rows 640000
IM scan rows projected 639999
IM scan rows valid 640000
physical reads 4
session logical reads 84570
session logical reads - IM 84462
session pga memory 18024752
table scans (IM) 111 rows selected.
性能和21c前的JSON列基本相同,慢了一点点(原文也是如此)。但空间效率胜出。
清理:
SQL> @14_json_cleanup.sql
Connected.
SQL>
SQL> alter table json_purchaseorder no inmemory;Table altered.SQL>
SQL> alter table j_purchaseorder drop constraint ensure_json;Table altered.SQL>
SQL> set echo off
实验 7: Automatic In-Memory 级别HIGH
背景知识
在 Oracle Database 18c 中添加了一个名为 Automatic In-Memory (AIM) 的特性。 AIM 的目标是根据使用情况管理 IM 列存储的内容。 AIM 最初有两个级别,LOW 和 MEDIUM,一旦 IM 列存储已满,就可以自动管理 IM 列存储内容。 在 Oracle Database 21c 中添加了第三个级别HIGH,它可以自动管理所有非系统段,而无需先启用内存中的对象。
本实验室将探索新的 AIM 级别 HIGH 及其工作原理。 将使用一个新模式,即具有小型、中型和大型表的 AIM 模式。 这将更容易展示 AIM 在列存储遇到“内存压力”(即已满)时如何工作。 SSB 模式中的 LINEORDER 表将用于帮助“填充”IM 列存储,然后 AIM 表将用于显示 AIM 如何管理对象总数以获得最大收益。
这几个大表位于aim schema,可以通过以下脚本创建,你无需执行。
create table lrgtab1 as select/*+ append */ * from ssb.lineorder where rownum <= 5000000;
create table lrgtab2 as select/*+ append */ * from ssb.lineorder where rownum <= 5000000;
create table lrgtab3 as select/*+ append */ * from ssb.lineorder where rownum <= 5000000;
create table lrgtab4 as select/*+ append */ * from ssb.lineorder where rownum <= 5000000;create table medtab1 as select /*+ append */ * from ssb.customer where rownum <= 300000;
create table medtab2 as select /*+ append */ * from ssb.customer where rownum <= 300000;
create table medtab3 as select /*+ append */ * from ssb.customer where rownum <= 300000;
create table medtab4 as select /*+ append */ * from ssb.customer where rownum <= 300000;create table smtab1 as select /*+ append */ * from ssb.supplier where rownum <= 20000;
create table smtab2 as select /*+ append */ * from ssb.supplier where rownum <= 20000;
create table smtab3 as select /*+ append */ * from ssb.supplier where rownum <= 20000;
create table smtab4 as select /*+ append */ * from ssb.supplier where rownum <= 20000;
此实验的主要脚本执行序列如下,后面会详述:
@02_disable_tables.sql
@03_pop_ssb_tables.sql
@04_im_populated.sql
@05_aim_attributes.sql
@06_aim_high.sql
@07_aim_attributes.sql
@08_im_populated.sql
@09_pop_aim_tables.sql
@10_im_populated.sql
@11_hm_stats.sql
@12_aimtasks.sql
@13_aimtaskdetails.sql
@14_aim_off.sql
@15_aim_attributes.sql
@16_im_populated.sql
@17_aim-high_cleanup.sql
实验前,需要执行以下:
. ~/.set-env-db.sh CDB1
进入aim-high目录,登录数据库:
cd /home/oracle/labs/inmemory/aim-high
sqlplus ssb/Ora_DB4U@localhost:1521/pdb1
调整显示:
set pages 9999
set lines 150
首先让我们检查 SSB 和 AIM 模式中对象的内存状态:
SQL> @01_aim_attributes.sql
Connected.
SQL>
SQL> -- Show table attributes
SQL>
SQL> select owner, table_name, NULL as partition_name, inmemory,2 inmemory_priority, inmemory_distribute, inmemory_compression3 from dba_tables4 where owner in ('AIM','SSB')5 UNION ALL6 select table_owner as owner, table_name, partition_name, inmemory,7 inmemory_priority, inmemory_distribute, inmemory_compression8 from dba_tab_partitions9 where table_owner in ('AIM','SSB')10 order by owner, table_name, partition_name;INMEMORY INMEMORY INMEMORY
OWNER TABLE_NAME PARTITION_NAME INMEMORY PRIORITY DISTRIBUTE COMPRESSION
---------- -------------------- --------------- ---------- ---------- ------------ --------------
AIM LRGTAB1 DISABLED
AIM LRGTAB2 DISABLED
AIM LRGTAB3 DISABLED
AIM LRGTAB4 DISABLED
AIM MEDTAB1 DISABLED
AIM MEDTAB2 DISABLED
AIM MEDTAB3 DISABLED
AIM SMTAB1 DISABLED
AIM SMTAB2 DISABLED
AIM SMTAB3 DISABLED
SSB CHICAGO_DATA DISABLED
SSB CUSTOMER DISABLED
SSB DATE_DIM DISABLED
SSB EXT_CUST_BULGARIA DISABLED
SSB EXT_CUST_NORWAY DISABLED
SSB JSON_PURCHASEORDER DISABLED
SSB J_PURCHASEORDER DISABLED
SSB LINEORDER PART_1994 DISABLED
SSB LINEORDER PART_1995 DISABLED
SSB LINEORDER PART_1996 DISABLED
SSB LINEORDER PART_1997 DISABLED
SSB LINEORDER PART_1998 DISABLED
SSB LINEORDER
SSB PART DISABLED
SSB SUPPLIER DISABLED25 rows selected.SQL>
SQL> set echo off
接下来,我们将验证所有的表都为 INMEMORY 禁用,以便我们可以确保我们将从干净的设置开始。
SQL> @02_disable_tables.sql
Connected.
alter table AIM.MEDTAB2 no inmemory
alter table AIM.SMTAB3 no inmemory
alter table AIM.LRGTAB3 no inmemory
alter table AIM.LRGTAB2 no inmemory
alter table AIM.LRGTAB1 no inmemory
alter table AIM.SMTAB1 no inmemory
alter table AIM.MEDTAB1 no inmemory
alter table AIM.MEDTAB3 no inmemory
alter table AIM.LRGTAB4 no inmemory
alter table AIM.SMTAB2 no inmemory
alter table SSB.SUPPLIER no inmemory
alter table SSB.DATE_DIM no inmemory
alter table SSB.PART no inmemory
alter table SSB.EXT_CUST_BULGARIA no inmemory
alter table SSB.EXT_CUST_NORWAY no inmemory
alter table SSB.CUSTOMER no inmemory
alter table SSB.CHICAGO_DATA no inmemory
alter table SSB.JSON_PURCHASEORDER no inmemory
alter table SSB.J_PURCHASEORDER no inmemory
alter table SSB.LINEORDER no inmemory
alter table SSB.LINEORDER modify partition PART_1994 no inmemory
alter table SSB.LINEORDER modify partition PART_1995 no inmemory
alter table SSB.LINEORDER modify partition PART_1996 no inmemory
alter table SSB.LINEORDER modify partition PART_1997 no inmemory
alter table SSB.LINEORDER modify partition PART_1998 no inmemoryPL/SQL procedure successfully completed.
现在我们将填充 LINEORDER 分区。 由于我们明确启用了 INMEMORY 分区,因此 AIM 不会触及它们。 这些分区将充当常量填充器,以便 IM 列存储接近满。 这将更容易确保 IM 列存储处于内存压力之下。 回想一下,这是 AIM 运行所必需的。
SQL> @03_pop_ssb_tables.sql
Connected.
SQL>
SQL> alter table ssb.lineorder inmemory priority high;Table altered.SQL>
SQL> exec dbms_inmemory.populate('SSB','LINEORDER');PL/SQL procedure successfully completed.SQL>
SQL> set echo off
验证是否填充了所有 LINEORDER 分区。
SQL> @04_im_populated.sql
Connected.
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 where owner not in ('AUDSYS','SYS')5 order by owner, segment_name, partition_name;In-Memory Bytes
OWNER SEGMENT_NAME PARTITION_NAME POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB LINEORDER PART_1994 COMPLETED 563,609,600 478,281,728 0
SSB LINEORDER PART_1995 COMPLETED 563,470,336 478,281,728 0
SSB LINEORDER PART_1996 COMPLETED 565,018,624 480,378,880 0
SSB LINEORDER PART_1997 COMPLETED 563,322,880 479,330,304 0
SSB LINEORDER PART_1998 COMPLETED 329,015,296 280,690,688 0SQL>
SQL> select * from v$inmemory_area;POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
-------------------------- ----------- ---------- --------------- ----------
1MB POOL 3252682752 2191523840 DONE 3
64KB POOL 201326592 5439488 DONE 3SQL>
SQL> set echo off
确认所有 LINEORDER 分区都已填充,然后再继续实验室。 您可能需要重新运行此脚本来验证分区是否已填充,因为完全填充分区确实需要一些时间。
让我们重新检查 SSB 和 AIM 模式中对象的内存状态:
SQL> @05_aim_attributes.sql
Connected.
SQL>
SQL> -- Show table attributes
SQL>
SQL> select owner, table_name, NULL as partition_name, inmemory,2 inmemory_priority, inmemory_distribute, inmemory_compression3 from dba_tables4 where owner in ('AIM','SSB')5 UNION ALL6 select table_owner as owner, table_name, partition_name, inmemory,7 inmemory_priority, inmemory_distribute, inmemory_compression8 from dba_tab_partitions9 where table_owner in ('AIM','SSB')10 order by owner, table_name, partition_name;INMEMORY INMEMORY INMEMORY
OWNER TABLE_NAME PARTITION_NAME INMEMORY PRIORITY DISTRIBUTE COMPRESSION
---------- -------------------- --------------- ---------- ---------- ------------ --------------
AIM LRGTAB1 DISABLED
AIM LRGTAB2 DISABLED
AIM LRGTAB3 DISABLED
AIM LRGTAB4 DISABLED
AIM MEDTAB1 DISABLED
AIM MEDTAB2 DISABLED
AIM MEDTAB3 DISABLED
AIM SMTAB1 DISABLED
AIM SMTAB2 DISABLED
AIM SMTAB3 DISABLED
SSB CHICAGO_DATA DISABLED
SSB CUSTOMER DISABLED
SSB DATE_DIM DISABLED
SSB EXT_CUST_BULGARIA DISABLED
SSB EXT_CUST_NORWAY DISABLED
SSB JSON_PURCHASEORDER DISABLED
SSB J_PURCHASEORDER DISABLED
SSB LINEORDER PART_1994 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1995 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1996 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1997 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1998 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER
SSB PART DISABLED
SSB SUPPLIER DISABLED25 rows selected.
请注意,LINEORDER 分区现在已启用内存,但所有其他对象的内存状态为空白或禁用。
现在我们将启用 AIM HIGH级别。
SQL> @06_aim_high.sql
Connected.NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
inmemory_automatic_level string OFFSystem altered.NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
inmemory_automatic_level string HIGH
让我们重新检查 SSB 和 AIM 模式中对象的内存状态:
SQL> @07_aim_attributes.sql
Connected.
SQL>
SQL> -- Show table attributes
SQL>
SQL> select owner, table_name, NULL as partition_name, inmemory,2 inmemory_priority, inmemory_distribute, inmemory_compression3 from dba_tables4 where owner in ('AIM','SSB')5 UNION ALL6 select table_owner as owner, table_name, partition_name, inmemory,7 inmemory_priority, inmemory_distribute, inmemory_compression8 from dba_tab_partitions9 where table_owner in ('AIM','SSB')10 order by owner, table_name, partition_name;INMEMORY INMEMORY INMEMORY
OWNER TABLE_NAME PARTITION_NAME INMEMORY PRIORITY DISTRIBUTE COMPRESSION
---------- -------------------- --------------- ---------- ---------- ------------ --------------
AIM LRGTAB1 ENABLED NONE AUTO AUTO
AIM LRGTAB2 ENABLED NONE AUTO AUTO
AIM LRGTAB3 ENABLED NONE AUTO AUTO
AIM LRGTAB4 ENABLED NONE AUTO AUTO
AIM MEDTAB1 ENABLED NONE AUTO AUTO
AIM MEDTAB2 ENABLED NONE AUTO AUTO
AIM MEDTAB3 ENABLED NONE AUTO AUTO
AIM SMTAB1 ENABLED NONE AUTO AUTO
AIM SMTAB2 ENABLED NONE AUTO AUTO
AIM SMTAB3 ENABLED NONE AUTO AUTO
SSB CHICAGO_DATA ENABLED NONE AUTO AUTO
SSB CUSTOMER ENABLED NONE AUTO AUTO
SSB DATE_DIM ENABLED NONE AUTO AUTO
SSB EXT_CUST_BULGARIA ENABLED NONE AUTO AUTO
SSB EXT_CUST_NORWAY ENABLED NONE AUTO AUTO
SSB JSON_PURCHASEORDER ENABLED NONE AUTO AUTO
SSB J_PURCHASEORDER ENABLED NONE AUTO AUTO
SSB LINEORDER PART_1994 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1995 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1996 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1997 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1998 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER
SSB PART ENABLED NONE AUTO AUTO
SSB SUPPLIER ENABLED NONE AUTO AUTO25 rows selected.SQL>
SQL> set echo off
请注意,现在所有表都在内存中启用,并注意除了 LINEORDER 分区之外的所有表都具有 AUTO 的内存压缩级别。 这是 AIM HIGH级别的新功能。
现在让我们看看 IM 列存储填充发生了什么。
SQL> @08_im_populated.sql
Connected.
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 where owner not in ('AUDSYS','SYS')5 order by owner, segment_name, partition_name;In-Memory Bytes
OWNER SEGMENT_NAME PARTITION_NAME POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB LINEORDER PART_1994 COMPLETED 563,609,600 478,281,728 0
SSB LINEORDER PART_1995 COMPLETED 563,470,336 478,281,728 0
SSB LINEORDER PART_1996 COMPLETED 565,018,624 480,378,880 0
SSB LINEORDER PART_1997 COMPLETED 563,322,880 479,330,304 0
SSB LINEORDER PART_1998 COMPLETED 329,015,296 280,690,688 0SQL>
SQL> select * from v$inmemory_area;POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
-------------------------- ----------- ---------- --------------- ----------
1MB POOL 3252682752 2191523840 DONE 3
64KB POOL 201326592 5439488 DONE 3SQL>
SQL> set echo off
没有什么不同。 请记住,AIM 仅在列存储处于内存压力下时运行,即使我们将 INMEMORY_AUTOMATIC_LEVEL 设置为高,对象仍然具有 NONE 优先级,这意味着必须先访问它们才能填充它们。 下一步将解决这个问题。
现在我们将访问四个 LRGTAB 表以开始填充这些表。
SQL> @09_pop_aim_tables.sql
Connected.
SQL>
SQL> select count(*) from lrgtab1;COUNT(*)
----------5000000SQL> select count(*) from lrgtab1;COUNT(*)
----------5000000SQL>
SQL> select count(*) from lrgtab2;COUNT(*)
----------5000000SQL> select count(*) from lrgtab2;COUNT(*)
----------5000000SQL> select count(*) from lrgtab2;COUNT(*)
----------5000000SQL>
SQL> select count(*) from lrgtab3;COUNT(*)
----------5000000SQL> select count(*) from medtab1;COUNT(*)
----------300000SQL> select count(*) from medtab1;COUNT(*)
----------300000SQL> select count(*) from medtab1;COUNT(*)
----------300000SQL> select count(*) from medtab2;COUNT(*)
----------300000SQL> select count(*) from medtab2;COUNT(*)
----------300000SQL> select count(*) from medtab2;COUNT(*)
----------300000SQL>
SQL> select count(*) from lrgtab4;COUNT(*)
----------5000000SQL> select count(*) from lrgtab4;COUNT(*)
----------5000000SQL>
SQL> set echo off
在此步骤中,我们将查看填充的段。 您可能需要多次运行此步骤以观察发布的进展情况。
SQL> @10_im_populated.sql
Connected.
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 where owner not in ('AUDSYS','SYS')5 order by owner, segment_name, partition_name;In-Memory Bytes
OWNER SEGMENT_NAME PARTITION_NAME POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB CUSTOMER COMPLETED 24,928,256 23,199,744 0
SSB DATE_DIM COMPLETED 122,880 1,179,648 0
SSB JSON_PURCHASEORDER OUT OF MEMORY 691,912,704 19,005,440 674,930,688
SSB J_PURCHASEORDER COMPLETED 793,198,592 946,077,696 0
SSB LINEORDER PART_1994 COMPLETED 563,609,600 478,281,728 0
SSB LINEORDER PART_1995 COMPLETED 563,470,336 478,281,728 0
SSB LINEORDER PART_1996 COMPLETED 565,018,624 480,378,880 0
SSB LINEORDER PART_1997 COMPLETED 563,322,880 479,330,304 0
SSB LINEORDER PART_1998 COMPLETED 329,015,296 280,690,688 0
SSB PART COMPLETED 56,893,440 16,973,824 0
SSB SUPPLIER COMPLETED 1,769,472 2,228,224 011 rows selected.SQL>
SQL> select * from v$inmemory_area;POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
-------------------------- ----------- ---------- --------------- ----------
1MB POOL 3252682752 3198156800 DONE 3
64KB POOL 201326592 7471104 DONE 3
此时,已经出现OUT OF MEMORY 现象。
让我们看一下各个细分市场的热图统计信息。 尽管 AIM 不直接使用热图,也不必启用 它AIM 才能工作,但它确实为我们提供了一种查看 AIM 决策所依据的使用统计数据的简单方法。
SQL> @11_hm_stats.sql
Connected.SEG SEG FULL LOOKUP NUM FULL NUM LOOKUP NUM SEG
OWNER OBJECT_NAME SUBOBJECT_NAME TRACK_TIME WRITE READ SCAN SCAN SCAN SCAN WRITE
---------- -------------------- --------------- ---------------- ---------- ---------- ---------- ---------- --------- ---------- ---------
SYS I_LTXID_TRANS$PK LTXID_TRANS_PK_ 11/09/2022 00:58 NO NO NO YES 0 1 001SYS LTXID_TRANS LTXID_TRANS_1 11/09/2022 00:58 NO NO NO YES 0 1 0
SSB CUSTOMER 11/09/2022 02:20 NO NO YES NO 5 0 0
SSB DATE_DIM 11/09/2022 02:20 NO NO YES NO 10 0 0
SSB LINEORDER PART_1994 11/09/2022 02:20 NO NO YES YES 16 1 0
SSB LINEORDER PART_1995 11/09/2022 02:20 NO NO YES YES 16 1 0
SSB LINEORDER PART_1996 11/09/2022 02:20 NO NO YES YES 18 24541 0
SSB LINEORDER PART_1997 11/09/2022 02:20 NO NO YES YES 18 1 0
SSB LINEORDER PART_1998 11/09/2022 02:20 NO NO YES YES 16 1 0
SSB LINEORDER_I2 PART_1994 11/09/2022 02:20 NO NO NO YES 0 1 0
SSB LINEORDER_I2 PART_1995 11/09/2022 02:20 NO NO NO YES 0 1 0
SSB LINEORDER_I2 PART_1996 11/09/2022 02:20 NO NO NO YES 0 1 0
SSB LINEORDER_I2 PART_1997 11/09/2022 02:20 NO NO NO YES 0 1 0
SSB LINEORDER_I2 PART_1998 11/09/2022 02:20 NO NO NO YES 0 1 0
SSB PART 11/09/2022 02:20 NO NO YES NO 7 0 0
SSB SUPPLIER 11/09/2022 02:20 NO NO YES NO 7 0 0
SSB LINEORDER_I1 PART_1996 11/09/2022 03:20 NO NO NO YES 0 1 0
SSB JSON_PURCHASEORDER 11/09/2022 04:20 NO NO YES NO 2 0 0
SSB J_PURCHASEORDER 11/09/2022 04:20 NO NO YES NO 4 0 0
AIM LRGTAB1 11/09/2022 04:36 NO YES YES NO 2 0 0
AIM LRGTAB2 11/09/2022 04:36 NO YES YES NO 3 0 0
AIM LRGTAB3 11/09/2022 04:36 NO YES YES NO 1 0 0
AIM LRGTAB4 11/09/2022 04:36 NO YES YES NO 2 0 0
AIM MEDTAB1 11/09/2022 04:36 NO YES YES NO 3 0 0
AIM MEDTAB2 11/09/2022 04:36 NO YES YES NO 3 0 025 rows selected.
显示的值将基于数据库中的使用情况。
现在让我们看看我们是否可以弄清楚 AIM 处理发生了什么。 首先,我们将查看作为 AIM 的一部分运行的任务。
SQL> @12_aimtasks.sql
Connected.TASK_ID CREATE_TIME STATE
---------- --------------------------- -------1 09-NOV-22 04:34:00 DONE2 09-NOV-22 04:34:13 DONE3 09-NOV-22 04:34:13 DONE4 09-NOV-22 04:34:14 DONE5 09-NOV-22 04:34:14 DONE6 09-NOV-22 04:34:14 DONE7 09-NOV-22 04:34:14 DONE8 09-NOV-22 04:34:14 DONE9 09-NOV-22 04:34:29 DONE10 09-NOV-22 04:34:30 DONE11 09-NOV-22 04:34:30 DONE12 09-NOV-22 04:34:31 DONE13 09-NOV-22 04:34:31 DONE14 09-NOV-22 04:34:31 DONE15 09-NOV-22 04:36:29 DONE16 09-NOV-22 04:36:33 DONE17 09-NOV-22 04:36:33 DONE17 rows selected.
记下最后一个 task_id。 我们将在下一步中使用它作为输入。 另请注意,这些任务大约每 2 分钟运行一次。 AIM 任务将在每个 IMCO 周期(大约每 2 分钟)安排一次,此时 IM 列存储处于内存压力之下。 这意味着在 IM 列存储中的 AIM 填充对象之前可能需要几个周期。
现在让我们看看 AIM 任务的详细信息,或者实际发生的情况。
SQL> @13_aimtaskdetails.sql
Connected.
Enter value for 1: 22
old 1: select * from dba_inmemory_aimtaskdetails where task_id = &1
new 1: select * from dba_inmemory_aimtaskdetails where task_id = 22TASK_ID OBJECT_OWNER OBJECT_NAME SUBOBJECT_NAME ACTION STATE
---------- --------------- ------------------------------ ------------------------------ ---------------- ----------22 AIM LRGTAB1 NO ACTION DONE22 AIM LRGTAB2 NO ACTION DONE22 AIM LRGTAB3 NO ACTION DONE22 AIM LRGTAB4 NO ACTION DONE22 AIM MEDTAB1 POPULATE DONE22 AIM MEDTAB2 POPULATE DONE22 AIM MEDTAB3 NO ACTION DONE22 AIM SMTAB1 NO ACTION DONE22 AIM SMTAB2 NO ACTION DONE22 AIM SMTAB3 NO ACTION DONE22 SSB CHICAGO_DATA NO ACTION DONE22 SSB CUSTOMER POPULATE DONE22 SSB DATE_DIM POPULATE DONE22 SSB EXT_CUST_BULGARIA NO ACTION DONE22 SSB EXT_CUST_NORWAY NO ACTION DONE22 SSB JSON_PURCHASEORDER NO ACTION DONE22 SSB J_PURCHASEORDER POPULATE DONE22 SSB LINEORDER PART_1994 POPULATE DONE22 SSB LINEORDER PART_1995 POPULATE DONE22 SSB LINEORDER PART_1996 POPULATE DONE22 SSB LINEORDER PART_1997 POPULATE DONE22 SSB LINEORDER PART_1998 POPULATE DONE22 SSB PART POPULATE DONE22 SSB SUPPLIER POPULATE DONE24 rows selected.
查看 OBJECT_NAME 和 ACTION。 现在 IM 列存储处于内存压力之下,AIM 已经接管了对发布的控制,而且还有很多事情要做。 根据使用情况统计,AIM 将填充对正在运行的查询产生最大益处的对象。 您可能想查看其他一些任务详细信息,以更好地了解所发生的情况。 还要注意,现在 AIM 正在控制发布,优先级将被忽略,AIM 将决定填充哪些对象以及驱逐哪些对象。
前面,我们看到JSON_PURCHASEORDER处于OUT OF MEMORY状态,对其多执行几次全表扫描,会将其它对象驱逐,为其留出内存:
select /*+ full(l) noparallel(l) */ count(*) from JSON_PURCHASEORDER l;
我们可以看到其成功发布了:
SQL> @10_im_populated.sql
Connected.
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 where owner not in ('AUDSYS','SYS')5 order by owner, segment_name, partition_name;In-Memory Bytes
OWNER SEGMENT_NAME PARTITION_NAME POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB CUSTOMER COMPLETED 24,928,256 23,199,744 0
SSB DATE_DIM COMPLETED 122,880 1,179,648 0
SSB JSON_PURCHASEORDER COMPLETED 691,912,704 841,940,992 0
SSB LINEORDER PART_1994 COMPLETED 563,609,600 478,281,728 0
SSB LINEORDER PART_1995 COMPLETED 563,470,336 478,281,728 0
SSB LINEORDER PART_1996 COMPLETED 565,018,624 480,378,880 0
SSB LINEORDER PART_1997 COMPLETED 563,322,880 479,330,304 0
SSB LINEORDER PART_1998 COMPLETED 329,015,296 280,690,688 0
SSB PART COMPLETED 56,893,440 16,973,824 0
SSB SUPPLIER COMPLETED 1,769,472 2,228,224 010 rows selected.SQL>
SQL> select * from v$inmemory_area;POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
-------------------------- ----------- ---------- --------------- ----------
1MB POOL 3252682752 3075473408 DONE 3
64KB POOL 201326592 7012352 DONE 3
实际上,对象J_PURCHASEORDER被清除出去(EVICT)了。
SQL> @13_aimtaskdetails.sql
Connected.
Enter value for 1: 44
old 1: select * from dba_inmemory_aimtaskdetails where task_id = &1
new 1: select * from dba_inmemory_aimtaskdetails where task_id = 44TASK_ID OBJECT_OWNER OBJECT_NAME SUBOBJECT_NAME ACTION STATE
---------- --------------- ------------------------------ ------------------------------ ---------------- ----------44 AIM LRGTAB1 EVICT DONE44 AIM LRGTAB2 EVICT DONE44 AIM LRGTAB3 EVICT DONE44 AIM LRGTAB4 EVICT DONE44 AIM MEDTAB1 EVICT DONE44 AIM MEDTAB2 EVICT DONE44 AIM MEDTAB3 EVICT DONE44 AIM SMTAB1 EVICT DONE44 AIM SMTAB2 EVICT DONE44 AIM SMTAB3 EVICT DONE44 SSB CHICAGO_DATA EVICT DONE44 SSB CUSTOMER NO ACTION DONE44 SSB DATE_DIM POPULATE DONE44 SSB EXT_CUST_BULGARIA EVICT DONE44 SSB EXT_CUST_NORWAY EVICT DONE44 SSB JSON_PURCHASEORDER PARTIAL POPULATE DONE44 SSB J_PURCHASEORDER EVICT DONE44 SSB LINEORDER PART_1994 POPULATE DONE44 SSB LINEORDER PART_1995 POPULATE DONE44 SSB LINEORDER PART_1996 POPULATE DONE44 SSB LINEORDER PART_1997 POPULATE DONE44 SSB LINEORDER PART_1998 POPULATE DONE44 SSB PART NO ACTION DONE44 SSB SUPPLIER NO ACTION DONE24 rows selected.
关闭AIM:
SQL> @14_aim_off.sql
Connected.NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
inmemory_automatic_level string HIGHSystem altered.NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
inmemory_automatic_level string OFF
让我们看看 inmemory 属性发生了什么变化。
SQL> @15_aim_attributes.sql
Connected.
SQL>
SQL> -- Show table attributes
SQL>
SQL> select owner, table_name, NULL as partition_name, inmemory,2 inmemory_priority, inmemory_distribute, inmemory_compression3 from dba_tables4 where owner in ('AIM','SSB')5 UNION ALL6 select table_owner as owner, table_name, partition_name, inmemory,7 inmemory_priority, inmemory_distribute, inmemory_compression8 from dba_tab_partitions9 where table_owner in ('AIM','SSB')10 order by owner, table_name, partition_name;INMEMORY INMEMORY INMEMORY
OWNER TABLE_NAME PARTITION_NAME INMEMORY PRIORITY DISTRIBUTE COMPRESSION
---------- -------------------- --------------- ---------- ---------- ------------ --------------
AIM LRGTAB1 DISABLED
AIM LRGTAB2 DISABLED
AIM LRGTAB3 DISABLED
AIM LRGTAB4 DISABLED
AIM MEDTAB1 DISABLED
AIM MEDTAB2 DISABLED
AIM MEDTAB3 DISABLED
AIM SMTAB1 DISABLED
AIM SMTAB2 DISABLED
AIM SMTAB3 DISABLED
SSB CHICAGO_DATA DISABLED
SSB CUSTOMER DISABLED
SSB DATE_DIM DISABLED
SSB EXT_CUST_BULGARIA DISABLED
SSB EXT_CUST_NORWAY DISABLED
SSB JSON_PURCHASEORDER DISABLED
SSB J_PURCHASEORDER DISABLED
SSB LINEORDER PART_1994 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1995 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1996 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1997 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER PART_1998 ENABLED HIGH AUTO FOR QUERY LOW
SSB LINEORDER
SSB PART DISABLED
SSB SUPPLIER DISABLED25 rows selected.SQL>
SQL> set echo offSQL> @16_im_populated.sql
Connected.
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 where owner not in ('AUDSYS','SYS')5 order by owner, segment_name, partition_name;In-Memory Bytes
OWNER SEGMENT_NAME PARTITION_NAME POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB LINEORDER PART_1994 COMPLETED 563,609,600 478,281,728 0
SSB LINEORDER PART_1995 COMPLETED 563,470,336 478,281,728 0
SSB LINEORDER PART_1996 COMPLETED 565,018,624 480,378,880 0
SSB LINEORDER PART_1997 COMPLETED 563,322,880 479,330,304 0
SSB LINEORDER PART_1998 COMPLETED 329,015,296 280,690,688 0SQL>
SQL> select * from v$inmemory_area;POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
-------------------------- ----------- ---------- --------------- ----------
1MB POOL 3252682752 2191523840 DONE 3
64KB POOL 201326592 5439488 DONE 3SQL>
SQL> set echo off
一切如初了。
运行清理脚本以重置热图统计信息,关闭 AIM 并为下一个 Lab 清除 IM 列存储。
SQL> @17_aim-high_cleanup.sql
Connected.System altered.Table altered.Connected.
alter table AIM.MEDTAB2 no inmemory
alter table AIM.SMTAB3 no inmemory
alter table AIM.LRGTAB3 no inmemory
alter table AIM.LRGTAB2 no inmemory
alter table AIM.LRGTAB1 no inmemory
alter table AIM.SMTAB1 no inmemory
alter table AIM.MEDTAB1 no inmemory
alter table AIM.MEDTAB3 no inmemory
alter table AIM.LRGTAB4 no inmemory
alter table AIM.SMTAB2 no inmemory
alter table SSB.SUPPLIER no inmemory
alter table SSB.DATE_DIM no inmemory
alter table SSB.PART no inmemory
alter table SSB.EXT_CUST_BULGARIA no inmemory
alter table SSB.EXT_CUST_NORWAY no inmemory
alter table SSB.CUSTOMER no inmemory
alter table SSB.CHICAGO_DATA no inmemory
alter table SSB.JSON_PURCHASEORDER no inmemory
alter table SSB.J_PURCHASEORDER no inmemory
alter table SSB.LINEORDER no inmemory
alter table SSB.LINEORDER modify partition PART_1994 no inmemory
alter table SSB.LINEORDER modify partition PART_1995 no inmemory
alter table SSB.LINEORDER modify partition PART_1996 no inmemory
alter table SSB.LINEORDER modify partition PART_1997 no inmemory
alter table SSB.LINEORDER modify partition PART_1998 no inmemoryPL/SQL procedure successfully completed.SQL> exec dbms_ilm_admin.CLEAR_HEAT_MAP_ALL;PL/SQL procedure successfully completed.
本实验演示了新的 INMEMORY_AUTOMATIC_LEVEL = HIGH 功能如何工作,以及 AIM 级别高如何启用对 IM 列存储内容的自动管理。 这意味着不再需要尝试找出哪些对象将从填充中获得最大收益。 现在数据库将为您自动完成。
实验 8: In-Memory Arithmetic
实验前,需要执行以下:
. ~/.set-env-db.sh CDB1
进入im-arith目录,登录数据库:
cd /home/oracle/labs/inmemory/im-arith
sqlplus ssb/Ora_DB4U@localhost:1521/pdb1
调整显示:
set pages 9999
set lines 150
此实验的主要脚本执行序列如下,后面会详述:
01_pre_arith.sql
02_im_usage.sql
03_enable_arith.sql
04_im_populated.sql
05_im_usage.sql
06_im_arith.sql
在运行以下实验之前,请确保SSB schema的5张表均已发布成功。如果没有发布,您可以执行setup目录下的以下脚本:
@04_im_alter_table.sql
@06_im_start_pop.sql
@08_im_populated.sql
在启用inmemory arithmetic前,运行脚本:
SQL> @01_pre_arith.sql
-- 耗时
Elapsed: 00:00:04.67-- 执行计划
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 4698 (100)| | | |
| 1 | SORT AGGREGATE | | 1 | 15 | | | | |
| 2 | PARTITION RANGE ALL | | 41M| 597M| 4698 (32)| 00:00:01 | 1 | 5 |
| 3 | TABLE ACCESS INMEMORY FULL| LINEORDER | 41M| 597M| 4698 (32)| 00:00:01 | 1 | 5 |
------------------------------------------------------------------------------------------------------------ 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 489
IM scan CUs columns accessed 234
IM scan CUs memcompress for query low 78
IM scan CUs pcode aggregation pushdown 156
IM scan rows 41760941
IM scan rows pcode aggregated 41760941
IM scan rows projected 78
IM scan rows valid 41760941
session logical reads 324181
session logical reads - IM 315483
session pga memory 19973768
table scans (IM) 512 rows selected.
查看内存使用情况:
SQL> @02_im_usage.sql
Connected.
SQL> column pool format a10;
SQL> column alloc_bytes format 999,999,999,999,999
SQL> column used_bytes format 999,999,999,999,999
SQL>
SQL> -- Show total column store usage
SQL>
SQL> SELECT pool, alloc_bytes, used_bytes, populate_status, con_id2 FROM v$inmemory_area;POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
---------- -------------------- -------------------- -------------------------- --------------------
1MB POOL 3,252,682,752 2,234,515,456 DONE 3
64KB POOL 201,326,592 6,029,312 DONE 3
启用inmemory arithmetic,需要重新发布:
SQL> @03_enable_arith.sql
Connected.
SQL>
SQL> -- This script will enable In-Memory optimized arithmetic
SQL>
SQL> alter table lineorder no inmemory;Table altered.SQL> alter table part no inmemory;Table altered.SQL> alter table supplier no inmemory;Table altered.SQL> alter table date_dim no inmemory;Table altered.SQL>
SQL> alter system set inmemory_optimized_arithmetic = 'ENABLE' scope=both;System altered.SQL>
SQL> alter table LINEORDER inmemory memcompress for query low;Table altered.SQL> alter table PART inmemory memcompress for query low;Table altered.SQL> alter table SUPPLIER inmemory memcompress for query low;Table altered.SQL> alter table DATE_DIM inmemory memcompress for query low;Table altered.SQL>
SQL> select /*+ full(LINEORDER) noparallel(LINEORDER) */ count(*) from LINEORDER;COUNT(*)
--------------------41760941SQL> select /*+ full(PART) noparallel(PART) */ count(*) from PART;COUNT(*)
--------------------800000SQL> select /*+ full(CUSTOMER) noparallel(CUSTOMER) */ count(*) from CUSTOMER;COUNT(*)
--------------------300000SQL> select /*+ full(SUPPLIER) noparallel(SUPPLIER) */ count(*) from SUPPLIER;COUNT(*)
--------------------20000SQL> select /*+ full(DATE_DIM) noparallel(DATE_DIM) */ count(*) from DATE_DIM;COUNT(*)
--------------------2556
确认发布完成:
SQL> @04_im_populated.sql
Connected.
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 order by owner, segment_name, partition_name;In-Memory Bytes
OWNER SEGMENT_NAME PARTITION_NAME POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB CUSTOMER COMPLETED 24,928,256 23,199,744 0
SSB DATE_DIM COMPLETED 122,880 1,179,648 0
SSB LINEORDER PART_1994 COMPLETED 563,609,600 590,479,360 0
SSB LINEORDER PART_1995 COMPLETED 563,470,336 585,236,480 0
SSB LINEORDER PART_1996 COMPLETED 565,018,624 587,333,632 0
SSB LINEORDER PART_1997 COMPLETED 563,322,880 585,236,480 0
SSB LINEORDER PART_1998 COMPLETED 329,015,296 342,556,672 0
SSB PART COMPLETED 56,893,440 20,119,552 0
SSB SUPPLIER COMPLETED 1,769,472 2,228,224 09 rows selected.
查看内存使用情况:
SQL> @05_im_usage.sql
Connected.
SQL> column pool format a10;
SQL> column alloc_bytes format 999,999,999,999,999
SQL> column used_bytes format 999,999,999,999,999
SQL>
SQL> -- Show total column store usage
SQL>
SQL> SELECT pool, alloc_bytes, used_bytes, populate_status, con_id2 FROM v$inmemory_area;POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
---------- -------------------- -------------------- --------------- --------------------
1MB POOL 3,252,682,752 2,731,540,480 DONE 3
64KB POOL 201,326,592 6,029,312 DONE 3
多用了近500M内存:
2,731,540,480-2,234,515,456=497,025,024
重新执行查询,性能提升18%,不算太明显(之前为4.67秒)
SQL> @06_im_arith.sql
-- 耗时
Elapsed: 00:00:03.97-- 执行计划
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 4698 (100)| | | |
| 1 | SORT AGGREGATE | | 1 | 15 | | | | |
| 2 | PARTITION RANGE ALL | | 41M| 597M| 4698 (32)| 00:00:01 | 1 | 5 |
| 3 | TABLE ACCESS INMEMORY FULL| LINEORDER | 41M| 597M| 4698 (32)| 00:00:01 | 1 | 5 |
------------------------------------------------------------------------------------------------------------ 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 400
IM scan CUs columns accessed 234
IM scan CUs memcompress for query low 78
IM scan CUs pcode aggregation pushdown 156
IM scan rows 41760941
IM scan rows pcode aggregated 41760941
IM scan rows projected 78
IM scan rows valid 41760941
session logical reads 315714
session logical reads - IM 315483
session pga memory 18483504
table scans (IM) 512 rows selected.
最后,重置参数为默认值:
SQL> alter system set inmemory_optimized_arithmetic = 'DISABLE' scope=both;System altered.
实验 9: In-Memory Hybrid Scan
实验前,需要执行以下:
. ~/.set-env-db.sh CDB1
进入hybrid-scans目录,登录数据库:
cd /home/oracle/labs/inmemory/hybrid-scans
sqlplus ssb/Ora_DB4U@localhost:1521/pdb1
调整显示:
set pages 9999
set lines 150
此实验的主要脚本执行序列如下,后面会详述:
01_pop_lineorder.sql
02_im_populated.sql
03_im_query.sql
04_pop_excluded.sql
05_im_populated.sql
06_im_columns.sql
07_hybrid_query.sql
08_hybrid_cleanup.sql
因为查询仅针对1996年的分区,因此先仅发布表的这个分区:
SQL> @01_pop_lineorder.sql
Connected.
SQL>
SQL> alter table lineorder no inmemory;Table altered.SQL>
SQL> alter table lineorder modify partition part_1996 inmemory;Table altered.SQL>
SQL> exec dbms_inmemory.populate(USER, 'LINEORDER', 'PART_1996');PL/SQL procedure successfully completed.SQL>
SQL> set echo off
查看发布状态:
SQL> @02_im_populated.sql
Connected.
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 order by owner, segment_name, partition_name;In-Memory Bytes
OWNER SEGMENT_NAME PARTITION_NAME POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB CUSTOMER COMPLETED 24,928,256 23,199,744 0
SSB DATE_DIM COMPLETED 122,880 1,179,648 0
SSB LINEORDER PART_1996 COMPLETED 565,018,624 480,378,880 0
SSB PART COMPLETED 56,893,440 16,973,824 0
SSB SUPPLIER COMPLETED 1,769,472 2,228,224 0
在未完全发布LINEORDER时,执行查询:
SQL> @03_im_query.sql-- 耗时
Elapsed: 00:00:00.08-- 执行计划
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 727 (100)| | | |
| 1 | SORT AGGREGATE | | 1 | 28 | | | | |
| 2 | PARTITION RANGE SINGLE | | 999 | 27972 | 727 (4)| 00:00:01 | 3 | 3 |
|* 3 | TABLE ACCESS INMEMORY FULL| LINEORDER | 999 | 27972 | 727 (4)| 00:00:01 | 3 | 3 |
----------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------3 - inmemory(("LO_ORDERDATE"=TO_DATE(' 1996-01-02 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND"LO_QUANTITY">40 AND "LO_SHIPMODE"='AIR'))filter(("LO_ORDERDATE"=TO_DATE(' 1996-01-02 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND"LO_QUANTITY">40 AND "LO_SHIPMODE"='AIR'))-- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 25
IM scan CUs columns accessed 68
IM scan CUs memcompress for query low 17
IM scan CUs pcode aggregation pushdown 17
IM scan rows 9126362
IM scan rows pcode aggregated 749
IM scan rows projected 17
IM scan rows valid 9126362
IM scan segments minmax eligible 17
physical reads 9
session logical reads 79109
session logical reads - IM 68972
session pga memory 19728688
table scans (IM) 114 rows selected.
排除掉一些列,这些列中包含了查询涉及的列:
SQL> @04_pop_excluded.sql
Connected.
SQL>
SQL> alter table lineorder no inmemory;Table altered.SQL>
SQL> alter table lineorder2 no inmemory (LO_ORDERPRIORITY,LO_SHIPPRIORITY,LO_EXTENDEDPRICE,LO_ORDTOTALPRICE,3 LO_DISCOUNT,LO_REVENUE,LO_SUPPLYCOST,LO_TAX,LO_COMMITDATE);Table altered.SQL>
SQL> alter table lineorder modify partition part_1996 inmemory;Table altered.SQL>
SQL> exec dbms_inmemory.populate(USER, 'LINEORDER', 'PART_1996');PL/SQL procedure successfully completed.
查看发布状态:
SQL> @05_im_populated.sql
SQL> @../imlogin.sql
SQL> connect ssb/Ora_DB4U@pdb1
Connected.
SQL>
SQL> set pages 9999
SQL> set lines 150
SQL> column owner format a10;
SQL> column segment_name format a20;
SQL> column partition_name format a15;
SQL> column populate_status format a15;
SQL> column bytes heading 'Disk Size' format 999,999,999,999
SQL> column inmemory_size heading 'In-Memory|Size' format 999,999,999,999
SQL> column bytes_not_populated heading 'Bytes|Not Populated' format 999,999,999,999
SQL> set echo on
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 order by owner, segment_name, partition_name;In-Memory Bytes
OWNER SEGMENT_NAME PARTITION_NAME POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB CUSTOMER COMPLETED 24,928,256 23,199,744 0
SSB DATE_DIM COMPLETED 122,880 1,179,648 0
SSB LINEORDER PART_1996 COMPLETED 565,018,624 214,040,576 0
SSB PART COMPLETED 56,893,440 16,973,824 0
SSB SUPPLIER COMPLETED 1,769,472 2,228,224 0
由于排除了一些列,因此内存的占用由480,378,880下降到214,040,576,减少约266M。
查看列的发布情况:
SQL> @06_im_columns.sql
Connected.
SQL>
SQL> select owner, table_name, COLUMN_NAME, INMEMORY_COMPRESSION2 from v$im_column_level3 where table_name = 'LINEORDER'4 order by table_name, segment_column_id;OWNER TABLE_NAME COLUMN_NAME INMEMORY_COMPRESSION
---------- -------------------- -------------------- --------------------------
SSB LINEORDER LO_ORDERKEY DEFAULT
SSB LINEORDER LO_LINENUMBER DEFAULT
SSB LINEORDER LO_CUSTKEY DEFAULT
SSB LINEORDER LO_PARTKEY DEFAULT
SSB LINEORDER LO_SUPPKEY DEFAULT
SSB LINEORDER LO_ORDERDATE DEFAULT
SSB LINEORDER LO_ORDERPRIORITY NO INMEMORY
SSB LINEORDER LO_SHIPPRIORITY NO INMEMORY
SSB LINEORDER LO_QUANTITY DEFAULT
SSB LINEORDER LO_EXTENDEDPRICE NO INMEMORY
SSB LINEORDER LO_ORDTOTALPRICE NO INMEMORY
SSB LINEORDER LO_DISCOUNT NO INMEMORY
SSB LINEORDER LO_REVENUE NO INMEMORY
SSB LINEORDER LO_SUPPLYCOST NO INMEMORY
SSB LINEORDER LO_TAX NO INMEMORY
SSB LINEORDER LO_COMMITDATE NO INMEMORY
SSB LINEORDER LO_SHIPMODE DEFAULT17 rows selected.
再次执行查询:
SQL> @07_hybrid_query.sql
-- 耗时
Elapsed: 00:00:00.02-- 执行计划
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 19067 (100)| | | |
| 1 | SORT AGGREGATE | | 1 | 28 | | | | |
| 2 | PARTITION RANGE SINGLE | | 999 | 27972 | 19067 (2)| 00:00:01 | 3 | 3 |
|* 3 | TABLE ACCESS INMEMORY FULL (HYBRID)| LINEORDER | 999 | 27972 | 19067 (2)| 00:00:01 | 3 | 3 |
-------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------3 - filter(("LO_ORDERDATE"=TO_DATE(' 1996-01-02 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND"LO_QUANTITY">40 AND "LO_SHIPMODE"='AIR'))-- 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 5
IM scan CUs columns accessed 51
IM scan CUs memcompress for query low 17
IM scan rows 9126362
IM scan rows valid 9126362
session logical reads 69823
session logical reads - IM 68972
session pga memory 18155824
table scans (IM) 19 rows selected.
注意执行计划中的第3行:TABLE ACCESS INMEMORY FULL (HYBRID)
怎么感觉性能还变快了?
最后执行清理:
alter table lineorder no inmemory;
alter table lineorder inmemory;
exec dbms_inmemory.populate(USER, 'LINEORDER');
实验 10: In-Memory Expression
实验前,需要执行以下:
. ~/.set-env-db.sh CDB1
进入ime目录,登录数据库:
cd /home/oracle/labs/inmemory/ime
sqlplus ssb/Ora_DB4U@localhost:1521/pdb1
此实验的主要脚本执行序列如下,后面会详述:
01_pre_ime.sql
02_im_usage.sql
03_create_ime.sql
04_im_populated.sql
05_ime_usage.sql
06_im_usage.sql
07_post_ime.sql
08_ime_ess.sql
在实验前,请确保lineorder表已发布。
在启用IME前,执行查询
SQL> @01_pre_ime.sql-- 耗时
Elapsed: 00:00:04.64-- 执行计划
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 5113 (100)| | | |
| 1 | HASH GROUP BY | | 7 | 161 | 5113 (38)| 00:00:01 | | |
| 2 | PARTITION RANGE ALL | | 41M| 916M| 5112 (38)| 00:00:01 | 1 | 5 |
| 3 | TABLE ACCESS INMEMORY FULL| LINEORDER | 41M| 916M| 5112 (38)| 00:00:01 | 1 | 5 |
------------------------------------------------------------------------------------------------------------ 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 466
IM scan CUs columns accessed 312
IM scan CUs memcompress for query low 78
IM scan CUs pcode aggregation pushdown 156
IM scan rows 41760941
IM scan rows pcode aggregated 41760941
IM scan rows projected 546
IM scan rows valid 41760941
session logical reads 315641
session logical reads - IM 315483
session pga memory 18155824
table scans (IM) 512 rows selected.
查看内存使用情况:
SQL> @02_im_usage.sql
Connected.
SQL> column pool format a10;
SQL> column alloc_bytes format 999,999,999,999,999
SQL> column used_bytes format 999,999,999,999,999
SQL>
SQL> -- Show total column store usage
SQL>
SQL> SELECT pool, alloc_bytes, used_bytes, populate_status, con_id2 FROM v$inmemory_area;POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
---------- -------------------- -------------------- -------------------------- --------------------
1MB POOL 3,252,682,752 2,234,515,456 DONE 3
64KB POOL 201,326,592 6,029,312 DONE 3SQL>
SQL> set echo off
创建inmemory expression:
SQL> @03_create_ime.sql
Connected.
SQL>
SQL> -- Create In-Memory Column Expression
SQL>
SQL> alter table lineorder no inmemory;Table altered.SQL> alter table lineorder add v1 invisible as (lo_ordtotalprice - (lo_ordtotalprice*(lo_discount/100)) + lo_tax);Table altered.SQL> alter table lineorder inmemory;Table altered.SQL> select count(*) from lineorder;COUNT(*)
--------------------41760941
查看发布情况:
SQL> @04_im_populated.sql
Connected.
SQL>
SQL> -- Query the view v$IM_SEGMENTS to shows what objects are in the column store
SQL> -- and how much of the objects were populated. When the BYTES_NOT_POPULATED is 0
SQL> -- it indicates the entire table was populated.
SQL>
SQL> select owner, segment_name, partition_name, populate_status, bytes,2 inmemory_size, bytes_not_populated3 from v$im_segments4 order by owner, segment_name, partition_name;In-Memory Bytes
OWNER SEGMENT_NAME PARTITION_NAME POPULATE_STATUS Disk Size Size Not Populated
---------- -------------------- --------------- --------------- ---------------- ---------------- ----------------
SSB CUSTOMER COMPLETED 24,928,256 23,199,744 0
SSB DATE_DIM COMPLETED 122,880 1,179,648 0
SSB LINEORDER PART_1994 COMPLETED 563,609,600 626,130,944 0
SSB LINEORDER PART_1995 COMPLETED 563,470,336 607,256,576 0
SSB LINEORDER PART_1996 COMPLETED 565,018,624 678,559,744 0
SSB LINEORDER PART_1997 COMPLETED 563,322,880 614,596,608 0
SSB LINEORDER PART_1998 COMPLETED 329,015,296 353,042,432 0
SSB PART COMPLETED 56,893,440 16,973,824 0
SSB SUPPLIER COMPLETED 1,769,472 2,228,224 09 rows selected.
查看inmemory expression的空间使用情况:
SQL> @05_ime_usage.sql
Connected.
SQL>
SQL> -- This query displays IMEUs populated in the In-Memory Column Store
SQL>
SQL> select2 o.owner,3 o.object_name,4 o.subobject_name as partition_name,5 i.column_name,6 count(*) t_imeu,7 sum(i.length)/1024/1024 space8 from9 v$im_imecol_cu i,10 dba_objects o11 where12 i.objd = o.object_id13 group by14 o.owner,15 o.object_name,16 o.subobject_name,17 i.column_name;Partition Column Total Used
Owner Object Name Name IMEUs Space(MB)
---------- -------------------- -------------------- --------------- ------- ------------
SSB LINEORDER PART_1998 V1 10 62
SSB LINEORDER PART_1997 V1 17 105
SSB LINEORDER PART_1996 V1 17 106
SSB LINEORDER PART_1995 V1 17 105
SSB LINEORDER PART_1994 V1 17 106
查看内存使用情况:
SQL> @06_im_usage.sql
Connected.
SQL> column pool format a10;
SQL> column alloc_bytes format 999,999,999,999,999
SQL> column used_bytes format 999,999,999,999,999
SQL>
SQL> -- Show total column store usage
SQL>
SQL> SELECT pool, alloc_bytes, used_bytes, populate_status, con_id2 FROM v$inmemory_area;POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
---------- -------------------- -------------------- --------------- --------------------
1MB POOL 3,252,682,752 2,917,138,432 DONE 3
64KB POOL 201,326,592 6,029,312 DONE 3
由于有内存表达式,因此内存消耗上涨了约650M。(2,917,138,432 - 2,234,515,456 = 682,622,976)
感觉没有完全对上,前面显示消耗为483M。
启用IME后,运行查询:
SQL> @07_post_ime.sql
-- 耗时
Elapsed: 00:00:01.45-- 执行计划
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 5343 (100)| | | |
| 1 | HASH GROUP BY | | 7 | 210 | 5343 (40)| 00:00:01 | | |
| 2 | PARTITION RANGE ALL | | 41M| 1194M| 5342 (40)| 00:00:01 | 1 | 5 |
| 3 | TABLE ACCESS INMEMORY FULL| LINEORDER | 41M| 1194M| 5342 (40)| 00:00:01 | 1 | 5 |
------------------------------------------------------------------------------------------------------------ 会话统计信息
NAME VALUE
-------------------------------------------------- --------------------
CPU used by this session 171
IM scan CUs columns accessed 312
IM scan CUs memcompress for query low 78
IM scan CUs pcode aggregation pushdown 156
IM scan EU rows 41760941
IM scan EUs columns accessed 78
IM scan EUs memcompress for query low 78
IM scan rows 41760941
IM scan rows pcode aggregated 41760941
IM scan rows projected 546
IM scan rows valid 41760941
session logical reads 325856
session logical reads - IM 315483
session pga memory 19990832
table scans (IM) 515 rows selected.
注意会话统计信息中的IM scan EU
关键字。
查看Expression Statistics Store (ESS)的使用情况:
SQL> @08_ime_ess.sql
Connected.
SQL>
SQL> -- Expression Statistics Store query
SQL>
SQL> col owner format a6;
SQL> col table_name format a15;
SQL> col expression_text format a70;
SQL> col evaluation_count format 9999999999999999;
SQL>
SQL> select2 -- owner,3 table_name,4 -- expression_id,5 evaluation_count,6 fixed_cost,7 expression_text8 from9 dba_expression_statistics10 where11 owner = 'SSB' and12 table_name = 'LINEORDER' and13 snapshot = 'LATEST'14 order by15 evaluation_count desc;TABLE_NAME EVALUATION_COUNT FIXED_COST EXPRESSION_TEXT
--------------- ----------------- ------------------------- ----------------------------------------------------------------------
LINEORDER 41762785 .0000000551081878534547 "LO_REVENUE"
LINEORDER 41762345 .0000000551081878534547 "LO_DISCOUNT"
LINEORDER 41761253 .0000110216375706909 "LO_ORDTOTALPRICE"-"LO_ORDTOTALPRICE"*("LO_DISCOUNT"/100)
LINEORDER 40465966 .0000000551081878534547 "LO_ORDTOTALPRICE"
LINEORDER 3170 .0000000551081878534547 "LO_SHIPMODE"
LINEORDER 1638 .0000137770469633637 "LO_ORDTOTALPRICE"-"LO_ORDTOTALPRICE"*("LO_DISCOUNT"/100)+"LO_TAX"
LINEORDER 1532 .0000000551081878534547 "LO_ORDERDATE"
LINEORDER 1517 .0000000551081878534547 "LO_QUANTITY"
LINEORDER 1092 .0000000551081878534547 "LO_TAX"9 rows selected.SQL>
SQL> --
SQL> -- Use the following to capture IM Expressions:
SQL> -- dbms_inmemory_admin.ime_capture_expressions('CURRENT');
SQL> --
SQL> set echo off
The Expression Statistics Store (ESS) is a repository maintained by the optimizer to store statistics about expression evaluation. The ESS resides in the SGA and persists on disk.
最后,执行清理:
alter table lineorder drop column v1;
Oracle 21版Database In-Memory LivaLabs实验(上)相关推荐
- oracle 11g duplicate database基于备份复制数据库(四)
不使用目标数据库的基于备份的复制,下面测试将原数据库使用备份复制到远程主机不同目录 1.对原数据库生成备份 RMAN> backup as compressed backupset databa ...
- oracle 11g duplicate database基于备份复制数据库(三)
不使用目标数据库的基于备份的复制,下面测试将原数据库使用备份复制到远程主机相同目录 1.对原数据库生成备份 RMAN> backup as compressed backupset databa ...
- oracle 11g duplicate database基于备份复制数据库(一)
使用目标数据库的基于备份的复制,下面测试将原数据库使用备份复制到远程主机相同目录. 1.对原数据库生成备份 RMAN> backup as compressed backupset databa ...
- oracle 11g duplicate database基于备份复制数据库(五)
不使用目标数据库和恢复目录基于备份的复制,下面测试将原数据库使用备份复制到远程主机相同目录 1.对原数据库生成备份 RMAN> backup as compressed backupset da ...
- oracle 11g duplicate database基于备份复制数据库(六)
不使用目标数据库和恢复目录基于备份的复制,下面测试将原数据库使用备份复制到远程主机不同目录 1.对原数据库生成备份 RMAN> backup as compressed backupset da ...
- oracle 11g duplicate database基于备份复制数据库(二)
使用目标数据库的基于备份的复制,下面测试将原数据库使用备份复制到远程主机不同目录 1.对原数据库生成备份 RMAN> backup as compressed backupset databas ...
- Oracle LiveLabs DB Security (数据库安全)实验汇总
在Oracle LiveLabs中,和数据库安全相关的实验分为2个系列,共12个实验. Oracle数据库安全架构如下图: 这些实验涉及了Oracle安全相关的特性,企业版选件,独立产品和服务. 关于 ...
- EDB PPAS(Oracle 兼容版) Oracle与PostgreSQL 兼容模式的参数配置切换
标签 PostgreSQL , EDB , PPAS , 参数 , Oracle模式 , PostgreSQL模式 背景 EDB PPAS是EDB推出的一款同时兼容Oracle和PostgreSQL协 ...
- Oracle复习(知识点、练习题、实验)
文章目录 第一章 数据库概念 数据库的三级模式结构:模式.外模式.内模式 三级模式之间的映射 第二章 Oracle12g体系结构 Oracle的逻辑存储结构 Oracle物理存储结构 Oracle11 ...
最新文章
- 那还剩下多少学习激情?
- 机器学习与高维信息检索 - Note 7 - 核主成分分析(Kernel Principal Component Analysis,K-PCA)
- python优秀程序员条件_Python 条件语句
- clion opencv安装_Clion+Opencv3.2终极配置教程
- 一篇文章学习Python中的多进程
- 通过printf从目标板到调试器的输出
- SVG 教程 (四)多边形,曲线,路径
- 软考网络工程师学习笔记4-局域网与城域网
- Internal Error 2738 - Installing ArcGIS Server 9.3,10 for Java
- IBM HMC V7R740虚拟机安装实战
- 基于嵌入式系统的gnash最小库依赖关系
- 从物理页面的争抢看linux内核内存管理
- 浙江计算机二级c语言考试,浙江计算机二级考试(C语言)上机试题
- 话单数据仓库搭建(1)- 数仓概念及数据采集
- 【练习/Python】监测汇率脚本
- 刘墉写给女儿的 忠告
- 编程实用工具大全(二)(前后端皆可用,不来看看?)
- 腾讯云4核8G服务器S5.LARGE8性能测评
- iphone游戏广告加载失败_iphone玩游戏怎么不弹广告
- 用Python编写一个ISBN查询工具,秒查图书信息
热门文章
- Docker容器技术 笔记
- 设置centos7.3的YUM源为国内阿里云源
- 每周一品 · 扬声器(喇叭)中的磁性材料
- 002如何构建hadoop集群环境?
- mysql mpp_MPP调研
- WordPress网站Logo
- ora-27100产生的原因分析
- 玩安卓从 0 到 1 之项目总结
- Google 后 Hadoop 时代的新 “三驾马车” -- Caffeine(搜索)、Pregel(图计算)、Dremel(查询)
- 用DIV+CSS技术设计的网页与实现制作【体育文化】dreamweaver学生网页设计