暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

GaussDB T 的创建脚本之:initplsql.sql 创建统计信息和变更信息过程和任务

原创 eygle 2019-12-09
1098

GaussDB T 的创建脚本中,initplsql.sql 负责创建了两个存储过程,分别是 gather_db_stats 用于收集数据库的统计信息;GATHER_CHANGE_STATS 用于收集数据库变化信息。

CREATE OR REPLACE PROCEDURE GATHER_DB_STATS(
estimate_percent NUMBER DEFAULT 10,
force BOOLEAN DEFAULT TRUE,
max_minutes INTEGER DEFAULT 360
)
–force false: don’t gather when cbo is disable
–max_minutes: default 6 hours
IS
cbo_enable VARCHAR(3);
start_time DATE;
curr_time DATE;
is_finish boolean;
snapshot_too_old EXCEPTION; – declare exception
PRAGMA EXCEPTION_INIT (snapshot_too_old, 715); – assign error code to exception
BEGIN
IF max_minutes < 1 OR max_minutes > 1440 THEN
RAISE_APPLICATION_ERROR(-20000, ‘max_minutes should between [1, 1440]’);
END IF;

--check cbo flag
IF force = FALSE THEN		
	SELECT VALUE INTO cbo_enable FROM SYS.DV_PARAMETERS WHERE NAME='CBO';
	IF UPPER(cbo_enable) = 'OFF' THEN
		RETURN;
	END IF;
END IF;

start_time := SYSDATE;

--only gather new heap table
LOOP
	is_finish := false;
	
	BEGIN
	FOR ITEM IN (SELECT OWNER, TABLE_NAME FROM ADM_TABLES WHERE TABLE_TYPE in ('HEAP', 'NOLOGGING') AND LAST_ANALYZED is NULL) 
	LOOP
		curr_time := SYSDATE;
		IF curr_time > (start_time + max_minutes/1440) THEN
			RETURN;
		END IF;
		
		BEGIN
			DBMS_STATS.GATHER_TABLE_STATS(ITEM.OWNER, ITEM.TABLE_NAME, null, estimate_percent);
		EXCEPTION
			WHEN OTHERS THEN
			  NULL;
		END;
	END LOOP;
	
	is_finish := true;
	
	EXCEPTION
	  WHEN snapshot_too_old THEN                         -- handle exception
		NULL;
	END;
	
	IF is_finish = true THEN
		EXIT; 
	END IF;
END LOOP;

--only gather heap table
LOOP
	is_finish := false;
	
	BEGIN
	FOR ITEM IN (SELECT OWNER, TABLE_NAME,LAST_ANALYZED FROM ADM_TABLES WHERE TABLE_TYPE in ('HEAP', 'NOLOGGING') AND 
				LAST_ANALYZED < start_time ORDER BY LAST_ANALYZED) 
	LOOP
		curr_time := SYSDATE;
		IF curr_time > (start_time + max_minutes/1440) THEN
			RETURN;
		END IF;
		
		BEGIN
			DBMS_STATS.GATHER_TABLE_STATS(ITEM.OWNER, ITEM.TABLE_NAME, null, estimate_percent);
		EXCEPTION
			WHEN OTHERS THEN
			  NULL;
		END;
	END LOOP;
	
	is_finish := true;
	
	EXCEPTION
	  WHEN snapshot_too_old THEN                         -- handle exception
		NULL;
	END;
	
	IF is_finish = true THEN
		EXIT; 
	END IF;
END LOOP;

END;
/

CREATE OR REPLACE PROCEDURE GATHER_CHANGE_STATS(
estimate_percent NUMBER DEFAULT 10,
change_percent NUMBER DEFAULT 10,
force BOOLEAN DEFAULT TRUE,
max_minutes NUMBER DEFAULT 60
)
–force false: don’t gather when cbo is disable
–max_minutes: default 1 hour
IS
cbo_enable VARCHAR(3);
start_time DATE;
curr_time DATE;
is_finish boolean;
snapshot_too_old EXCEPTION; – declare exception
PRAGMA EXCEPTION_INIT (snapshot_too_old, 715); – assign error code to exception
BEGIN
IF max_minutes < 1 OR max_minutes > 1440 THEN
RAISE_APPLICATION_ERROR(-20000, ‘max_minutes should between [1, 1440]’);
END IF;

--check cbo flag
IF force = FALSE THEN		
	SELECT VALUE INTO cbo_enable FROM SYS.DV_PARAMETERS WHERE NAME='CBO';
	IF UPPER(cbo_enable) = 'OFF' THEN
		RETURN;
	END IF;
END IF;
	
start_time := SYSDATE;
--flush modification to table
DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO();	

--(1)gather the new table
LOOP
	is_finish := false;
	
	BEGIN
	FOR ITEM IN (SELECT OWNER, TABLE_NAME FROM ADM_TABLES WHERE TABLE_TYPE in ('HEAP', 'NOLOGGING') AND LAST_ANALYZED is NULL) 
	LOOP	
		curr_time := SYSDATE;
		IF curr_time > (start_time + max_minutes/1440) THEN
			RETURN;
		END IF;
					
		BEGIN
			DBMS_STATS.GATHER_TABLE_STATS(ITEM.OWNER, ITEM.TABLE_NAME, NULL, estimate_percent);
		EXCEPTION
			WHEN OTHERS THEN
			  NULL;
		END;
	END LOOP;
	
	is_finish := true;
	
	EXCEPTION
		WHEN snapshot_too_old THEN                         -- handle exception
		NULL;
	END;
	
	IF is_finish = true THEN
		EXIT; 
	END IF;
END LOOP;

--(2)gather the table changed 
LOOP
	is_finish := false;
	
	BEGIN
	FOR ITEM IN (SELECT A.OWNER, A.TABLE_NAME, A.LAST_ANALYZED FROM ADM_TABLES A, ADM_TAB_MODIFICATIONS B 
	WHERE A.TABLE_TYPE in ('HEAP', 'NOLOGGING') AND A.OWNER = B.TABLE_OWNER AND A.TABLE_NAME=B.TABLE_NAME 
	AND B.PARTITION_NAME IS NULL AND A.LAST_ANALYZED < start_time AND
		((NVL(B.INSERTS, 0) + NVL(B.UPDATES, 0) + NVL(B.DELETES, 0))>= (CHANGE_PERCENT * A.NUM_ROWS/100))
		ORDER BY A.LAST_ANALYZED) 
	LOOP	
		curr_time := SYSDATE;
		IF curr_time > (start_time + max_minutes/1440) THEN
			RETURN;
		END IF;
					
		BEGIN
			DBMS_STATS.GATHER_TABLE_STATS(ITEM.OWNER, ITEM.TABLE_NAME, NULL, estimate_percent);
		EXCEPTION
			WHEN OTHERS THEN
			  NULL;
		END;
	END LOOP;
	
	is_finish := true;
	
	EXCEPTION
		WHEN snapshot_too_old THEN                         -- handle exception
		NULL;
	END;
	
	IF is_finish = true THEN
		EXIT; 
	END IF;
END LOOP;

--(3)gather the new partition 
LOOP
	is_finish := false;
	
	BEGIN
	FOR ITEM IN (SELECT U.NAME AS OWNER, T.NAME AS TABLE_NAME, TP.NAME AS PARTITION_NAME
	   FROM SYS.SYS_USERS U JOIN SYS.SYS_TABLES T ON U.ID = T.USER# 
	   JOIN SYS.SYS_TABLE_PARTS TP ON T.USER# = TP.USER# AND T.ID = TP.TABLE# AND TP.ANALYZETIME IS NULL)
	LOOP	
		curr_time := SYSDATE;
		IF curr_time > (start_time + max_minutes/1440) THEN
			RETURN;
		END IF;
					
		BEGIN
			DBMS_STATS.GATHER_TABLE_STATS(ITEM.OWNER, ITEM.TABLE_NAME, ITEM.PARTITION_NAME, estimate_percent);				
		EXCEPTION
			WHEN OTHERS THEN
			  NULL;
		END;
	END LOOP;
	
	is_finish := true;
	
	EXCEPTION
		WHEN snapshot_too_old THEN                         -- handle exception
		NULL;
	END;
	
	IF is_finish = true THEN
		EXIT; 
	END IF;
END LOOP;

--(4)gather the partition changed 
LOOP
	is_finish := false;
	
	BEGIN
	FOR ITEM IN (SELECT U.NAME AS OWNER, T.NAME AS TABLE_NAME, TP.NAME AS PARTITION_NAME, TP.ANALYZETIME
	   FROM SYS.SYS_USERS U JOIN SYS.SYS_TABLES T ON U.ID = T.USER# 
	   JOIN SYS.SYS_TABLE_PARTS TP ON T.USER# = TP.USER# AND T.ID = TP.TABLE#
	   JOIN SYS.SYS_DML_STATS MO ON T.USER# = MO.USER# AND T.ID = MO.TABLE# AND MO.PART# = TP.PART# 
	   WHERE MO.PARTED = 1 AND MO.PART# <> -1 AND TP.ANALYZETIME < start_time AND
	   ((NVL(MO.INSERTS, 0) + NVL(MO.UPDATES, 0) + NVL(MO.DELETES, 0))>= (CHANGE_PERCENT * TP.ROWCNT/100))
	   ORDER BY TP.ANALYZETIME) 
	LOOP	
		curr_time := SYSDATE;
		IF curr_time > (start_time + max_minutes/1440) THEN
			RETURN;
		END IF;
					
		BEGIN
			DBMS_STATS.GATHER_TABLE_STATS(ITEM.OWNER, ITEM.TABLE_NAME, ITEM.PARTITION_NAME, estimate_percent);				
		EXCEPTION
			WHEN OTHERS THEN
			  NULL;
		END;
	END LOOP;
	
	is_finish := true;
	
	EXCEPTION
		WHEN snapshot_too_old THEN                         -- handle exception
		NULL;
	END;
	
	IF is_finish = true THEN
		EXIT; 
	END IF;
END LOOP;

END;
/

DECLARE
JOBNO NUMBER;
JOB_COUNT NUMBER;
BEGIN
SELECT COUNT(*) INTO JOB_COUNT FROM SYS_JOBS WHERE WHAT LIKE ‘%GATHER_DB_STATS%’;
IF JOB_COUNT = 0 THEN
DBMS_JOB.SUBMIT(JOBNO,‘GATHER_DB_STATS(estimate_percent=>10, force=>FALSE);’, TRUNC(SYSDATE+1) + 1/24, ‘TRUNC(sysdate+1) +1/24’);
DBMS_JOB.BROKEN(JOBNO,true);
COMMIT;
END IF;
END;
/

DECLARE
JOBNO NUMBER;
JOB_COUNT NUMBER;
BEGIN
SELECT COUNT(*) INTO JOB_COUNT FROM SYS_JOBS WHERE WHAT LIKE ‘%GATHER_CHANGE_STATS%’;
IF JOB_COUNT = 0 THEN
DBMS_JOB.SUBMIT(JOBNO,‘GATHER_CHANGE_STATS(estimate_percent=>10, change_percent=>10, force=>FALSE);’, SYSDATE, ‘SYSDATE+15/24/60’);
DBMS_JOB.BROKEN(JOBNO,true);
COMMIT;
END IF;
END;
/

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论