请教问题:MERGE INTO导致CPU占用率非常高

吹雪 吹雪 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
服务器搭在虚拟机上:
CPU: 2 * 4核
内存: 16GB
硬盘: 60GB

操作系统: RHEL 6.4 x86-64
数据库: ORACLE 11.2


该服务器当作数据库服务器+WEB服务器(TOMCAT)使用,设计ORACLE分配8GB内存,TOMCAT分配4.5GB内存。


ORACLE内存设置:
alter system set memory_target=6g;
alter system set memory_max_target=8g;
alter system set db_keep_cache_size=384m;
alter system set sga_target=4g;
alter system set sga_max_size=6g;
alter system set pga_aggregate_target=2g;



主要有一个记录表(设计预计每月记录约1亿条,该表需保存5年以上数据):
CREATE TABLE Records
(
Record_Id NUMBER CONSTRAINT PK_RECORDS PRIMARY KEY,
Record_Terminal NUMBER NOT NULL,
Record_Window NUMBER(4) NOT NULL,
Record_Employee NVARCHAR2(50) ,
Record_Number NVARCHAR2(50) NOT NULL,
Record_Business NUMBER NOT NULL,
Record_Status NUMBER(4) NOT NULL,
Record_Evaluation NUMBER(4) NOT NULL,
Record_TicketTime DATE NOT NULL,
Record_AcceptTime DATE ,
Record_FinishTime DATE ,
Record_VIP NUMBER NOT NULL,
Record_BookChannel NUMBER NOT NULL,
Record_Description1 NVARCHAR2(255) ,
Record_Description2 NVARCHAR2(1024) ,
-- 仅 11g以上支持虚拟列
Record_PartitionField NUMBER(3) GENERATED ALWAYS AS (MOD(TO_NUMBER(TO_CHAR(Record_TicketTime,'y')),2)*100+TO_NUMBER(TO_CHAR(Record_TicketTime,'mm'))) VIRTUAL
)PCTFREE 10,PCTUSED 75
PARTITION BY LIST (Record_PartitionField)
(
PARTITION P01 VALUES (1) TABLESPACE qms_records_01,
PARTITION P02 VALUES (2) TABLESPACE qms_records_02,
PARTITION P03 VALUES (3) TABLESPACE qms_records_03,
PARTITION P04 VALUES (4) TABLESPACE qms_records_04,
PARTITION P05 VALUES (5) TABLESPACE qms_records_05,
PARTITION P06 VALUES (6) TABLESPACE qms_records_06,
PARTITION P07 VALUES (7) TABLESPACE qms_records_07,
PARTITION P08 VALUES (8) TABLESPACE qms_records_08,
PARTITION P09 VALUES (9) TABLESPACE qms_records_09,
PARTITION P10 VALUES (10) TABLESPACE qms_records_10,
PARTITION P11 VALUES (11) TABLESPACE qms_records_11,
PARTITION P12 VALUES (12) TABLESPACE qms_records_12,
PARTITION P13 VALUES (101) TABLESPACE qms_records_13,
PARTITION P14 VALUES (102) TABLESPACE qms_records_14,
PARTITION P15 VALUES (103) TABLESPACE qms_records_15,
PARTITION P16 VALUES (104) TABLESPACE qms_records_16,
PARTITION P17 VALUES (105) TABLESPACE qms_records_17,
PARTITION P18 VALUES (106) TABLESPACE qms_records_18,
PARTITION P19 VALUES (107) TABLESPACE qms_records_19,
PARTITION P20 VALUES (108) TABLESPACE qms_records_20,
PARTITION P21 VALUES (109) TABLESPACE qms_records_21,
PARTITION P22 VALUES (110) TABLESPACE qms_records_22,
PARTITION P23 VALUES (111) TABLESPACE qms_records_23,
PARTITION P24 VALUES (112) TABLESPACE qms_records_24
);


WEB端定期会有一批数据需MERGE INTO到RECORDS表里(约15000条/分钟),大部分是需要UPDATE的,小部分使用INSERT。
实际测试时,发现ORACLE进程占用CPU相当高,Load Average都在8.0以上,MERGE INTO的操作速度很慢;同时,查看内存还有很大空余(8GB以上),Oracle只占用了4.0GB内存(相当于我为SGA_TARGET指定的值)。
WEB端使用一个CONNECTION或多个CONNECTION进行操作,效果都差不多。

WEB端JAVA使用prepareStatement进行SQL预编译,然后传入参数,通过addBatch批量传入待更新记录(批量大小各种值都测试过,不理想),最后executeBatch进行执行并commit。

MERGE INTO的语句如下:
MERGE INTO Records r1
USING (SELECT 1 FROM DUAL) r2
ON(
r1.record_tickettime BETWEEN TO_DATE('2014-09-25','yyyy-mm-dd') AND TO_DATE('2014-09-25 23:59:59','yyyy-mm-dd hh24:mi:ss')
AND r1.record_terminal=1
AND r1.record_business=1
AND r1.record_number='VIP1000'
)
WHEN MATCHED THEN
UPDATE SET r1.record_window=1,
r1.record_employee='100001',
r1.record_status=80,
r1.record_evaluation=80,
r1.record_vip=0,
r1.record_bookchannel=2,
r1.record_description1='这里是客户信息,是调用ESB服务获取到的'
WHEN NOT MATCHED THEN
INSERT(record_id,record_terminal,record_window,record_employee,
record_number,record_business,record_status,record_evaluation,
record_tickettime,record_vip,record_bookchannel)
VALUES(seq_record_id.NEXTVAL,1,1,'100002','VIP1000',1,1,2,
TO_DATE('2014-09-25 12:34:56','yyyy-mm-dd hh24:mi:ss'),1,2);

...全文
评论 4
收藏 已收藏
分享
返回顶部
吹雪
Oracle 高级技术 3,499 成员 18,710 内容