前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >运维技巧 - 活用临时表隔离冷热数据

运维技巧 - 活用临时表隔离冷热数据

作者头像
数据和云
发布2018-03-07 16:27:20
7740
发布2018-03-07 16:27:20
举报
文章被收录于专栏:数据和云数据和云

编辑手记:Oracle给了我们很多工具,在日常数据库管理中活用这些工具方可发挥最大效能。

作者简介: 张洪涛 富士康 DBA

在数据库监控过程中发现考勤数据库上Employees_ControlData存储过程执行时间需20分钟。这个存储过程逻辑很简单,就是打开一个游标,做LOOP循环,再删除重复数据,结构如下:

CREATE OR REPLACE PROCEDURE Employees_ControlData IS tmpVar NUMBER(6); tmpVar1 NUMBER(6); tmpVar2 NUMBER (6); tmpVar3 NUMBER(6); CURSOR EMP_NO IS SELECT WORKNO FROM ZZ_EMPLOYEES; BEGIN --LINE 12行 FOR USERID INEMP_NO LOOP ...... END LOOP;

--Line128行,删除重复数据

Delete .... ; COMMIT; EXCEPTION WHEN NO_DATA_FOUND THEN NULL; WHEN OTHERS THEN -- Consider logging the error and then re-raise RAISE; END Employees_Controldata;

ZZ_EMPLOYEES有4万多笔数据,LOOP也会执行4万多次。AWR报告与GridControl监控都显示效能瓶颈在LOOP循环中六处SQL,再看一下LOOP循环中六处问题SQL:

--Line14行

SELECT COUNT(*) INTO tmpVar FROM CPYTGL.EMPLOYEE_CONTROL WHERE EMP_NO = USERID.WORKNO ANDTO_CHAR(INOROUT_TIME,'YYYY/MM/DD')= TO_CHAR(SYSDATE-2,'YYYY/MM/DD') AND TYPE='F' AND INOROUT_TIME >SYSDATE-3 AND ROWNUM<6;

--Line38行

INSERT INTOEMPLOYEE_CONTROL_EXCEPTION SELECT DISTINCT * FROM EMPLOYEE_CONTROL WHERE EMP_NO = USERID.WORKNO AND TO_CHAR(INOROUT_TIME,'YYYY/MM/DD')= TO_CHAR(SYSDATE-2,'YYYY/MM/DD') AND TYPE='F' AND INOROUT_TIME >SYSDATE-3;

--Line49行

INSERT INTOEMPLOYEE_CONTROL_EXCEPTION SELECT DISTINCT * FROM EMPLOYEE_CONTROL WHERE EMP_NO = USERID.WORKNO AND TO_CHAR(INOROUT_TIME,'YYYY/MM/DD')= TO_CHAR(SYSDATE-2,'YYYY/MM/DD') AND TYPE='F' AND INOROUT_TIME >SYSDATE-3 AND INOROUT_TIME NOTIN (SELECT INOROUT_TIME FROM EMPLOYEE_CONTROL_EXCEPTION WHERE EMP_NO = USERID.WORKNO AND TO_CHAR(INOROUT_TIME, 'YYYY/MM/DD')= TO_CHAR(SYSDATE-2, 'YYYY/MM/DD') AND TYPE='F' AND INOROUT_TIME >SYSDATE-3);

--Line72行

SELECT COUNT(*) INTO tmpVar1 FROM CPYTGL.EMPLOYEE_CONTROL WHERE EMP_NO = USERID.WORKNO ANDTO_CHAR(INOROUT_TIME,'YYYY/MM/DD')= TO_CHAR(SYSDATE-2,'YYYY/MM/DD') AND TYPE='L' AND INOROUT_TIME >SYSDATE-3 AND ROWNUM<6;

--Line82行

INSERT INTO EMPLOYEE_CONTROL_EXCEPTION SELECT DISTINCT * FROM EMPLOYEE_CONTROL WHERE EMP_NO = USERID.WORKNO AND TO_CHAR(INOROUT_TIME,'YYYY/MM/DD')= TO_CHAR(SYSDATE-2,'YYYY/MM/DD') AND TYPE='L' AND INOROUT_TIME >SYSDATE-3;

--Line87行

INSERT INTO EMPLOYEE_CONTROL_EXCEPTION SELECT DISTINCT * FROM EMPLOYEE_CONTROL WHERE EMP_NO = USERID.WORKNO AND TO_CHAR(INOROUT_TIME,'YYYY/MM/DD')= TO_CHAR(SYSDATE-2,'YYYY/MM/DD') AND TYPE='L' AND INOROUT_TIME >SYSDATE-3 AND INOROUT_TIME NOTIN(SELECTINOROUT_TIME FROM EMPLOYEE_CONTROL_EXCEPTION WHERE EMP_NO = USERID.WORKNO AND TO_CHAR(INOROUT_TIME, 'YYYY/MM/DD')= TO_CHAR(SYSDATE-2, 'YYYY/MM/DD') AND TYPE='L' AND INOROUT_TIME >SYSDATE-3);

这六处SQL都查询了EMPLOYEE_CONTROL考勤信息表。此表已有近两亿笔数据,根据INOROUT_TIME字段进行分区,并对相关字段建立了索引。

CREATE INDEX EMPLOYEE_CONTROL_EMPNOINOROUT ON EMPLOYEE_CONTROL (TO_CHAR("INOROUT_TIME",'YYYY/MM/DD'),EMP_NO) LOCAL; SQL> SELECT column_name 2 FROM dba_part_key_columns 3 WHERE name = 'EMPLOYEE_CONTROL'; COLUMN_NAME -------------------------------------------------------------------------------- INOROUT_TIME SQL> SELECT num_rows 2 FROM dba_tables 3 WHERE table_name = 'EMPLOYEE_CONTROL'; NUM_ROWS ---------- 193585044

EMPLOYEE_CONTROL考勤信息表至少需保留一年数据备查。六条SQL已加INOROUT_TIME >SYSDATE-3条件,执行计划中可进行分区裁剪,删减数据这条路行不通。

WHERE中的条件也正确使用了索引,似乎所有常规优化方法都已用上,如何才能进一步提升存储过程LOOP循环执行速度?

我们再分析这六条SQL,在WHERE条件中都出现了对EMPLOYEE_CONTROL表以下限定条件:

TO_CHAR(INOROUT_TIME,'YYYY/MM/DD')= TO_CHAR(SYSDATE-2,'YYYY/MM/DD') AND INOROUT_TIME >SYSDATE-3 AND TYPE='L' AND TYPE='F'

存储过程实际要读取的只有一天的数据,这部分数据一般只有10万笔为热点数据。如果我们先把此部分数据单独读出,在LOOP循环中就可只读取临时表内容,避免4万次读取有两亿笔数据的EMPLOYEE_CONTROL考勤资料表。

依此思路,我们先建立一个临时表,并为临时表EMP_NO字段添加索引:

CREATE GLOBAL TEMPORARY TABLE CPYTGL.EMPLOYEE_CONTROL_TEMP ON COMMIT DELETE ROWS AS SELECT * FROMCPYTGL.EMPLOYEE_CONTROL WHERE 1 = 0; CREATE INDEX CPYTGL.EMPLOYEE_CONTROL_TEMP_NOON CPYTGL.EMPLOYEE_CONTROL_TEMP (EMP_NO);

再在存储过程头部将符合条件的数据取出:

INSERT INTO cpytgl.EMPLOYEE_CONTROL_TEMP SELECT* FROM CPYTGL.EMPLOYEE_CONTROL WHERE TO_CHAR (INOROUT_TIME, 'YYYY/MM/DD') = TO_CHAR(SYSDATE - 2, 'YYYY/MM/DD') AND INOROUT_TIME > SYSDATE- 3 AND TYPE IN('F', 'L');

这样就可改写消耗资源的六条SQL查询临时表。以第14行SQL为例,需改写为:

--Line14行

SELECT COUNT (*) INTO tmpVar FROM cpytgl.EMPLOYEE_CONTROL_TEMP WHERE EMP_NO = USERID.WORKNO AND TYPE = 'F' AND ROWNUM< 6;

LOOP循环中六条SQL改为查询10万笔记录的临时表后,存储过程只需1分钟即可跑完。相较之前20分钟运行时间有大幅度提升。

此例核心为使用临时表隔离冷热数据。DBA一次调优不一定能想出最佳方法,通过对应用的不断深入观察,以及Oracle工具的合理使用,加上一点点灵光一现那些看似解决不了的难题都可一一化解。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-07-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据和云 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档