Oracle使用临时表与直接关联的性能比较

济南小老虎 / 2023-05-13 / 原文

Oracle使用临时表与直接关联的性能比较


摘要

自己的数据库水平还是太low了. 
之前有很多店理解过. 但是一直理解的不深入.
比如我们这边有很多使用临时表存储中间结果数据
然后对结果数据进行关联查询的

直接关联查询

SELECT
	col.TABLE_NAME,
	col.column_name 
FROM
	user_constraints con,
	user_cons_columns col 
WHERE
	con.constraint_name = col.constraint_name 
	AND con.constraint_type = 'P' 
	AND col.Table_name NOT IN (
	SELECT
		table_name 
	FROM
		(
		SELECT
			count( col.TABLE_NAME ),
			col.TABLE_NAME 
		FROM
			user_constraints con,
			user_cons_columns col 
		WHERE
			con.constraint_name = col.constraint_name 
			AND con.constraint_type = 'P' 
			AND col.TABLE_NAME IN ( SELECT TABLE_NAME FROM user_tables WHERE num_rows > 1 ) 
		GROUP BY
			col.TABLE_NAME 
		HAVING
			(
			count( col.TABLE_NAME )) > 1 
		)) 
	AND col.TABLE_NAME IN ( SELECT TABLE_NAME FROM user_tables WHERE num_rows > 1 )

SQL说明

从 user_constraints 取出来唯一主键的名称
从 user_cons_columns 取出来唯一主键对应的表名和列名
从 user_tables 取出来存在数据的表信息.
然后排除掉有符合主键的情况. 

得到单一主键的表名和列名信息. 

耗时和执行计划分析

使用navicat 执行此段SQL
我这边大概 200G的数据库 1万多个表的情况下
耗时6550 秒 一小时五十分钟. 

使用sqlplus 展示执行计划

set autotrace on 
set autotrace traceonly 
set autotrace traceonly explain
set autotrace traceonly statistics
set pagesize 2000
set linesize 2000

explain plan for somesql
查看具体执行计划
select * from table(dbms_xplan.display());

简历两个中间表进行查询的结果

BEGIN
   EXECUTE IMMEDIATE 'DROP TABLE zhaobsh001';
EXCEPTION
   WHEN OTHERS THEN
      IF SQLCODE != -942 THEN
         RAISE;
      END IF;
END;
/
create table zhaobsh001 as select col.TABLE_NAME,col.column_name from user_constraints con,user_cons_columns col where con.constraint_name=col.constraint_name and con.constraint_type='P' and col.TABLE_NAME in (select TABLE_NAME from user_tables where num_rows > 1 );
BEGIN
   EXECUTE IMMEDIATE 'DROP TABLE zhaobsh002';
EXCEPTION
   WHEN OTHERS THEN
      IF SQLCODE != -942 THEN
         RAISE;
      END IF;
END;
/
create table zhaobsh002 as select table_name  from (select count(col.TABLE_NAME),col.TABLE_NAME from user_constraints con,user_cons_columns col where con.constraint_name=col.constraint_name and con.constraint_type='P' and col.TABLE_NAME in (select TABLE_NAME from user_tables where num_rows > 1 ) group by col.TABLE_NAME  having(count(col.TABLE_NAME)) > 1 ) ;
BEGIN
   EXECUTE IMMEDIATE 'DROP TABLE zhaobsh003';
EXCEPTION
   WHEN OTHERS THEN
      IF SQLCODE != -942 THEN
         RAISE;
      END IF;
END;
/
create table zhaobsh003  as select  table_name,column_name from zhaobsh001 where  TABLE_NAME not in (select table_name from zhaobsh002) ;

select 'select count(upper('||column_name||')) as  '|| table_name ||' , upper('||column_name||') from '||table_name||' group by upper('||column_name||') having count(upper('||column_name||')) >1 ; ' from zhaobsh003

子表查询的情况

删除表耗时:0.02秒左右
创建三个表的分别耗时:
zhaobsh001: 2.954秒
zhaobsh002: 3.163秒
zhaobsh003: 0.018秒

查询SQL集合耗时:0.13秒
累计耗时: 8秒钟左右
性能提升非常明显. (从6000多秒到不到10秒钟)

感想

不要总是想一句SQL出结果
应该多考虑产品一些实现.
他们是耗费了很多经理的产出物
有时候不仅要看网上的东西,还应该多学习产品里面优秀的设计要点.