今天有个客户数据库负载比较高,查询发现sql用了 like %ABC% 这种写法,并且应用方面还无法改写成等值条件,下面进行测试。 (客户生产表的这个列唯一值比较高,并且表的列很多有三十多个,如果列比较少或者like %ABC%或取的值比较多的话下面的建议不适用。) 首先创建测试表 create table tt as select * from dba_objects; SQL> alter system flush buffer_cache; System altered. SQL> SELECT OBJECT_ID, OBJECT_TYPE, OBJECT_NAME FROM TT WHERE OBJECT_NAME LIKE '%ZC%'; 44000 JAVA CLASS oracle/net/resolver/EZConnectResolver 47203 JAVA CLASS oracle/jdbc/driver/TSTZCopyingBinder 47205 JAVA CLASS oracle/jdbc/driver/TSLTZCopyingBinder Execution Plan ---------------------------------------------------------- Plan hash value: 264906180 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 3664 | 178K| 395 (1)| 00:00:01 | |* 1 | TABLE ACCESS FULL| TT | 3664 | 178K| 395 (1)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("OBJECT_NAME" LIKE '%ZC%' AND "OBJECT_NAME" IS NOT NULL) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 1423 consistent gets 1419 physical reads 0 redo size 915 bytes sent via SQL*Net to client 448 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 3 rows processed 未作处理前的consistent gets 大约 1400 进行sql改写,并创建索引,测试性能。 SQL> create index t_name on TT(OBJECT_NAME); Index created. SQL> exec dbms_stats.gather_table_stats('ZC','TT',no_invalidate=>false); PL/SQL procedure successfully completed. SQL> alter system flush buffer_cache; System altered. SQL> SELECT OBJECT_ID, OBJECT_TYPE, OBJECT_NAME FROM TT WHERE OBJECT_NAME IN (SELECT OBJECT_NAME FROM TT WHERE OBJECT_NAME LIKE '%ZC%'); 47205 JAVA CLASS oracle/jdbc/driver/TSLTZCopyingBinder 47203 JAVA CLASS oracle/jdbc/driver/TSTZCopyingBinder 44000 JAVA CLASS oracle/net/resolver/EZConnectResolver Execution Plan ---------------------------------------------------------- Plan hash value: 1780297486 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 3664 | 304K| 523 (1)| 00:00:01 | |* 1 | HASH JOIN RIGHT SEMI | | 3664 | 304K| 523 (1)| 00:00:01 | |* 2 | INDEX FAST FULL SCAN| T_NAME | 3664 | 125K| 128 (1)| 00:00:01 | |* 3 | TABLE ACCESS FULL | TT | 3664 | 178K| 395 (1)| 00:00:01 | -------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("OBJECT_NAME"="OBJECT_NAME") 2 - filter("OBJECT_NAME" LIKE '%ZC%' AND "OBJECT_NAME" IS NOT NULL) 3 - filter("OBJECT_NAME" LIKE '%ZC%' AND "OBJECT_NAME" IS NOT NULL) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 487 consistent gets 485 physical reads 0 redo size 915 bytes sent via SQL*Net to client 506 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 3 rows processed sql 改写后 大约490,还是有比较明显的效果的。 或者下面这种写法: select /*+no_merge(b) use_nl(t b)*/ t.OBJECT_ID, t.OBJECT_TYPE, t.OBJECT_NAME from TT t, (select rowid from TT a where a.OBJECT_NAME like '%ZC%') b where t.rowid = b.rowid; Elapsed: 00:00:00.04 Execution Plan ---------------------------------------------------------- Plan hash value: 3989423677 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 3664 | 264K| 3792 (1)| 00:00:01 | | 1 | NESTED LOOPS | | 3664 | 264K| 3792 (1)| 00:00:01 | | 2 | VIEW | | 3664 | 43968 | 128 (1)| 00:00:01 | |* 3 | INDEX FAST FULL SCAN | T_NAME | 3664 | 168K| 128 (1)| 00:00:01 | | 4 | TABLE ACCESS BY USER ROWID| TT | 1 | 62 | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): -------------------------------------------------- 3 - filter("A"."OBJECT_NAME" LIKE '%ZC%' AND "A"."OBJECT_NAME" IS NOT NULL) Hint Report (identified by operation id / Query Block Name / Object Alias): Total hints for statement: 1 (U - Unused (1)) --------------------------------------------------------------------------- 1 - SEL$1 / B@SEL$1 U - use_nl(t b) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 479 consistent gets 0 physical reads 0 redo size 915 bytes sent via SQL*Net to client 537 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 3 rows processed consistent gets也比较低。 测试instr函数性能 SQL> alter system flush buffer_cache; SELECT OBJECT_ID, OBJECT_TYPE, OBJECT_NAME FROM TT WHERE instr(OBJECT_NAME, 'ZC') >0; System altered. Execution Plan ---------------------------------------------------------- Plan hash value: 264906180 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 3664 | 178K| 395 (1)| 00:00:01 | |* 1 | TABLE ACCESS FULL| TT | 3664 | 178K| 395 (1)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(INSTR("OBJECT_NAME",'ZC')>0) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 1423 consistent gets 1419 physical reads 0 redo size 915 bytes sent via SQL*Net to client 447 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 3 rows processed instr和like %ZC% 差距不大,但是如果带入的变量ZC是个定值,我们可以考虑创建基于函数的索引进行优化。 SQL> create index idx_tt2 on tt(instr(OBJECT_NAME,'ZC')); Index created. SQL> exec dbms_stats.gather_table_stats('ZC','TT',no_invalidate=>false); PL/SQL procedure successfully completed. SQL> set linesize 1000 SQL> SELECT /*+ index (TT IDX_TT2 )*/ OBJECT_ID, OBJECT_TYPE, OBJECT_NAME FROM TT WHERE INSTR(OBJECT_NAME, 'ZC') >0; Execution Plan ---------------------------------------------------------- Plan hash value: 1462875822 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 54953 | 2844K| 1167 (1)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| TT | 54953 | 2844K| 1167 (1)| 00:00:01 | |* 2 | INDEX RANGE SCAN | IDX_TT2 | 54953 | | 101 (0)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access(INSTR("OBJECT_NAME",'ZC')>0) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 5 consistent gets 0 physical reads 0 redo size 915 bytes sent via SQL*Net to client 474 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 3 rows processed consistent gets 下降特别明显。 SELECT /*+ index (TT IDX_TT2 )*/ OBJECT_ID, OBJECT_TYPE, OBJECT_NAME FROM TT WHERE INSTR(OBJECT_NAME, 'ZC') >0,测试的时候发现,这个sql不加hint 不会走索引,怀疑是clustering_factor的原因。 exec dbms_stats.SET_INDEX_STATS('ZC','IDX_TT2', clstfct=>10); SQL> SELECT OBJECT_ID,OBJECT_NAME,OBJECT_TYPE FROM TT WHERE instr(OBJECT_NAME, 'ZC') >0; Elapsed: 00:00:00.01 Execution Plan ---------------------------------------------------------- Plan hash value: 1462875822 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 54953 | 2844K| 110 (1)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| TT | 54953 | 2844K| 110 (1)| 00:00:01 | |* 2 | INDEX RANGE SCAN | IDX_TT2 | 54953 | | 101 (0)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): -------------------------------------------------- 2 - access(INSTR("OBJECT_NAME",'ZC')>0) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 5 consistent gets 0 physical reads 0 redo size 915 bytes sent via SQL*Net to client 446 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 3 rows processed
优化
来源:这里教程网
时间:2026-03-03 20:03:35
作者:
编辑推荐:
- 优化03-03
- adg 的tempfile 和 offline datafile03-03
- 在11g到19c的迁移过程中发现一个sql语法方面的问题03-03
- oracle主机虚拟内存不足导致实例宕机03-03
- Oracle 23ai FREE安装初体验03-03
- REHL7.6静默安装Oracle19C,泰裤了!03-03
- 数据库管理-第195期 Oracle & RDMA(20240527)03-03
- oracle 区分32位还是64位03-03
下一篇:
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
热文推荐
- oracle主机虚拟内存不足导致实例宕机
oracle主机虚拟内存不足导致实例宕机
26-03-03 - Oracle 23ai FREE安装初体验
Oracle 23ai FREE安装初体验
26-03-03 - REHL7.6静默安装Oracle19C,泰裤了!
REHL7.6静默安装Oracle19C,泰裤了!
26-03-03 - 数据库管理-第195期 Oracle & RDMA(20240527)
数据库管理-第195期 Oracle & RDMA(20240527)
26-03-03 - 数据库管理-第187期 23ai:怎么用SQL创建图(20240510)
数据库管理-第187期 23ai:怎么用SQL创建图(20240510)
26-03-03 - 数据库管理-第186期 23ai:啥?我还能干掉Neo4j?(20240509)
- rac asm新增磁盘报0RA-15333或ORA-15075
rac asm新增磁盘报0RA-15333或ORA-15075
26-03-03 - Oracle RAC的排障案例一则
Oracle RAC的排障案例一则
26-03-03 - 测试开发新技能:Oracle到高斯数据库的无缝迁移
测试开发新技能:Oracle到高斯数据库的无缝迁移
26-03-03 - 因Oracle 23ai,甲骨文中国罕见的开了个会
因Oracle 23ai,甲骨文中国罕见的开了个会
26-03-03
