# Purpose: generate a simple statistic for all static queries
# contact: stefan.reil@de.ibm.com

# version 3.1 (22/06/2009)
# introduced option to analyze DELAYES QUERIES only ==> use "delayed=1" option
# modified output headers 

# version 3 (12/12/2008
# added leng option to differentiate Dynamic queries
# fixed runtime calculation inaccuracy
# introduced automatic output sort according to overall runtime

# USAGE
# generates a summary for each query with overall runtime, number of executions and avg runtime
# output will be sorted automatically on overall runtime in ascending order
# Dynamic queries can be differentiated by providing optional parameter "leng"
# If db.log tracks only DELAYED QUERIES, option "delayed=1" can be used to diagnose those

# ===> awk -f sumall.awk [leng=<dynamic queries first n characters parameter>] [delayed=1] db.log[*] 

# the script prints a first and last processed querytimestamp at the end.  This timestamp will show the 
# correct timerange covered in the db.log files, when they are given to the script in the correct order
# start with oldest logs first e.g.
# awk -f sumall.awk leng=70 db.log.3 db.log.2 db.log.1 db.log 


BEGIN{
	cnt = 0;
	config = 0;
}
{
	# set variables according to input parameters
	if(config == 0){
		if(leng <=0){
			leng = 0;
		}
		if(delayed <=0){
			POSADDCNT = 7;
			SEARCHSTRING = "Time:";
		}
		else {
			SEARCHSTRING = "DELAYED QUERY";
			POSADDCNT = 15;
		}
		config = 1;
	}
	
	pos = index($0,SEARCHSTRING);
	if(pos > 0){
		# get the query runtime
		split(substr($0,pos + POSADDCNT),v,"ms");
		time = v[1];
		# get queries execution timestamp
		stamp1 = $1;
		stamp2 = $2;
		# remember the first processed queries timestamp
		if (cnt <= 1){
			start1 = stamp1;
			start2 = stamp2;
			cnt =5;
		}
		getline;
		if($1 ~ /Static/){
			sql[$4,1]+=time;
			sql[$4,2]+=1;
		}
		else {
			if($1 ~ /Dynamic/ && time >= 0){
				if (index($0,"]") > 0){
					sqlstr = substr($0,1,index($0,"]"));
				}
				else{
					# get the full SQL string from all consecutive lines, till end terminator ] is found
					while (index($0,"]")<=0){
						for (i=1; i<NF+1; i++){
							sqlstr = sqlstr " " $i;
						}
					getline;
					}
				}
				# remember ony the first n characters of the SQL string as defined with leng parameter
				sqlshort = "Dynamic " substr(sqlstr,index(sqlstr,"["),leng);
				sqlstr = "";
            }
	        sql[sqlshort,1] += time;
			sql[sqlshort,2] += 1;
			dynsum += time;
			dyncnt += 1;
		}
	}
}
END{
	# create the unique list of sqlnames
	command = "sort -n | uniq > xysumall_sort_tmpxy"	# uniq needed to avoid duplication of sql names due to awk array usage
	for(x in sql){
		split(x, splitv, SUBSEP);
		print sql[splitv[1],1]";" splitv[1] | command;
	}
	close (command);

	# read sorted list
	cnt=1;
	while ((getline line < "xysumall_sort_tmpxy") > 0){
		split(line,vec,";");
		mysortl[cnt] = vec[2];
		cnt++;
	}
	#delete the temp sort file from filesystem as it is no longer used
	system("rm xysumall_sort_tmpxy 2>&1 > /dev/null");

	# print sqls in ascending runtime order ==> using mysortl
	printf("\nStatistics per query\n");
	printf("%-10s %-10s %-10s\n","millisecs","count","average runtime");
	printf("%-10s %-10s %-10s %-10s \n", "sum(ms)", "cnt", "avg(ms)", "QUERY");	
	for (e=1; e<cnt; e++){
		printf("%-10d %-10d %-10d %-20s\n", sql[mysortl[e],1], sql[mysortl[e],2],sql[mysortl[e],1] / sql[mysortl[e],2] ,mysortl[e]);
		totalsum += sql[mysortl[e],1];
		totalcnt += sql[mysortl[e],2];
	}
	printf("%-10s %-10s %-10s %-10s \n", "sum(ms)", "cnt", "avg(ms)", "QUERY");	
	
	printf("\nStatistical values for all queries\n");
	printf("%-10s %-10s %-10s\n","millisecs","count","average runtime");
	printf("%-10s %-10s %-10s %-10s","(ms)","(cnt)","(avg)","Total runtime in hours:");

	totalaverage=0;
	if( totalcnt != 0 ) {
		totalaverage = totalsum / totalcnt;
	} 
	
	printf("\n %-10d %-10d %-10d %-5f \n\n", totalsum, totalcnt,totalaverage, totalsum/3600000);
	
	printf("out of which dynamic queries account for \n");
	printf("%-10s %-10s %-10s %-10s\n","(ms)","(cnt)","(avg)","Total runtime in hours:");
	
	dynaverage=0;
	if( dyncnt != 0 ) {
		dynaverage = dynsum / dyncnt;
	} 
	printf("%-10d %-10d %-10d %-5f \n\n", dynsum, dyncnt, dynaverage, dynsum/3600000);
	
	print "first processed querytimestamp: "stamp1, stamp2 ;
	print "last  processed querytimestamp: " start1, start2 ;
	
	# printf("\n use \"awk -f sumsql.awk leng=<stringlength> db.lo*\"  to distinguish Dynamic queries with specified stringlength");
	# printf("\n use \"awk -f sumsql.awk leng=<stringlength> delayed=1 db.lo*\"  to parse DELAYED QUERIES only");

}

