mysql的性能优化工具(源自韩锋大师,针对5.7修改)
                                            
                                                
                韩锋大师分享了一个MySQL的性能优化工具,一个能自动采集SQL优化相关各种信息的python脚本,对于优化人员而言,这能省不少事,赞!
试用了一下,发现在mysql5.7下,运行不起来,细节上还是有好几个坑的,费了一些周折,终于把坑踩完了,现在把细节说明一下,并把修改后的SQL分享出来;
问题1:调用脚本时,若SQL是用单引号包含(韩老师就是这么示范的:python mysql_tuning.py -p tuning_sql.ini -s 'select xxx),但这样会报错,解决办法:用双引号分隔,如:python mysql_tuning.py -p tuning_sql.ini -s "select * from employees.dept_emp"这样就没问题;
问题2:没有引用string单元,在使用string.atoi时会报错,解决办法:import string;
问题3:mysql5.7后,infomation_schema的几个表INFORMATION_SCHEMA.GLOBAL_VARIABLES、INFORMATION_SCHEMA.SESSION_VARIABLES、 INFORMATION_SCHEMA.SESSION_STATUS要替换成performance_schema下的;
问题4:在显示执行计划时,table与type也是有可能是NULL的,要做空值处理,另外没有显示partitions栏位;
问题5:p_after_status[key]有可能是小数,所以用int去转换会报错,需要用float;
问题6:db_name显示成user_pwd了,这个或者不算问题;
修改后的脚本如下:
						
                
            
                                                            
网站名称:mysql的性能优化工具(源自韩锋大师,针对5.7修改)
文章地址:http://www.cqwzjz.cn/article/ghjpds.html
                                            
                                        试用了一下,发现在mysql5.7下,运行不起来,细节上还是有好几个坑的,费了一些周折,终于把坑踩完了,现在把细节说明一下,并把修改后的SQL分享出来;
问题1:调用脚本时,若SQL是用单引号包含(韩老师就是这么示范的:python mysql_tuning.py -p tuning_sql.ini -s 'select xxx),但这样会报错,解决办法:用双引号分隔,如:python mysql_tuning.py -p tuning_sql.ini -s "select * from employees.dept_emp"这样就没问题;
问题2:没有引用string单元,在使用string.atoi时会报错,解决办法:import string;
问题3:mysql5.7后,infomation_schema的几个表INFORMATION_SCHEMA.GLOBAL_VARIABLES、INFORMATION_SCHEMA.SESSION_VARIABLES、 INFORMATION_SCHEMA.SESSION_STATUS要替换成performance_schema下的;
问题4:在显示执行计划时,table与type也是有可能是NULL的,要做空值处理,另外没有显示partitions栏位;
问题5:p_after_status[key]有可能是小数,所以用int去转换会报错,需要用float;
问题6:db_name显示成user_pwd了,这个或者不算问题;
修改后的脚本如下:
点击(此处)折叠或打开

在怀来等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供网站设计、网站制作 网站设计制作按需求定制网站,公司网站建设,企业网站建设,高端网站设计,成都全网营销,外贸营销网站建设,怀来网站建设费用合理。
- 
				#!/usr/local/bin/python
 
- 
				import datetime
 
- 
				import getopt
 
- 
				import sys
 
- 
				import string
 
- 
				import pprint
 
- 
				from warnings import filterwarnings
 
- 
				import MySQLdb
 
- 
				import ConfigParser
 
- 
				import sqlparse
 
- 
				from sqlparse.sql import IdentifierList, Identifier
 
- 
				from sqlparse.tokens import Keyword, DML
 
- 
				
 
- 
				filterwarnings('ignore', category = MySQLdb.Warning)
 
- 
				
 
- 
				seq1="+"
 
- 
				seq2="-"
 
- 
				seq3="|"
 
- 
				
 
- 
				SYS_PARM_FILTER = (
 
- 
				    'BINLOG_CACHE_SIZE',
 
- 
				    'BULK_INSERT_BUFFER_SIZE',
 
- 
				    'HAVE_PARTITION_ENGINE',
 
- 
				    'HAVE_QUERY_CACHE',
 
- 
				    'INTERACTIVE_TIMEOUT',
 
- 
				    'JOIN_BUFFER_SIZE',
 
- 
				    'KEY_BUFFER_SIZE',
 
- 
				    'KEY_CACHE_AGE_THRESHOLD',
 
- 
				    'KEY_CACHE_BLOCK_SIZE',
 
- 
				    'KEY_CACHE_DIVISION_LIMIT',
 
- 
				    'LARGE_PAGES',
 
- 
				    'LOCKED_IN_MEMORY',
 
- 
				    'LONG_QUERY_TIME',
 
- 
				    'MAX_ALLOWED_PACKET',
 
- 
				    'MAX_BINLOG_CACHE_SIZE',
 
- 
				    'MAX_BINLOG_SIZE',
 
- 
				    'MAX_CONNECT_ERRORS',
 
- 
				    'MAX_CONNECTIONS',
 
- 
				    'MAX_JOIN_SIZE',
 
- 
				    'MAX_LENGTH_FOR_SORT_DATA',
 
- 
				    'MAX_SEEKS_FOR_KEY',
 
- 
				    'MAX_SORT_LENGTH',
 
- 
				    'MAX_TMP_TABLES',
 
- 
				    'MAX_USER_CONNECTIONS',
 
- 
				    'OPTIMIZER_PRUNE_LEVEL',
 
- 
				    'OPTIMIZER_SEARCH_DEPTH',
 
- 
				    'QUERY_CACHE_SIZE',
 
- 
				    'QUERY_CACHE_TYPE',
 
- 
				    'QUERY_PREALLOC_SIZE',
 
- 
				    'RANGE_ALLOC_BLOCK_SIZE',
 
- 
				    'READ_BUFFER_SIZE',
 
- 
				    'READ_RND_BUFFER_SIZE',
 
- 
				    'SORT_BUFFER_SIZE',
 
- 
				    'SQL_MODE',
 
- 
				    'TABLE_CACHE',
 
- 
				    'THREAD_CACHE_SIZE',
 
- 
				    'TMP_TABLE_SIZE',
 
- 
				    'WAIT_TIMEOUT'
 
- 
				) 
 
- 
				
 
- 
				def is_subselect(parsed):
 
- 
				    if not parsed.is_group():
 
- 
				        return False
 
- 
				    for item in parsed.tokens:
 
- 
				        if item.ttype is DML and item.value.upper() == 'SELECT':
 
- 
				            return True
 
- 
				    return False
 
- 
				
 
- 
				def extract_from_part(parsed):
 
- 
				    from_seen = False
 
- 
				    for item in parsed.tokens:
 
- 
				        #print item.ttype,item.value
 
- 
				        if from_seen:
 
- 
				            if is_subselect(item):
 
- 
				                for x in extract_from_part(item):
 
- 
				                    yield x
 
- 
				            elif item.ttype is Keyword:
 
- 
				                raise StopIteration
 
- 
				            else:
 
- 
				                yield item
 
- 
				        elif item.ttype is Keyword and item.value.upper() == 'FROM':
 
- 
				            from_seen = True
 
- 
				
 
- 
				def extract_table_identifiers(token_stream):
 
- 
				    for item in token_stream:
 
- 
				        if isinstance(item, IdentifierList):
 
- 
				            for identifier in item.get_identifiers():
 
- 
				                yield identifier.get_real_name()
 
- 
				        elif isinstance(item, Identifier):
 
- 
				            yield item.get_real_name()
 
- 
				        # It's a bug to check for Keyword here, but in the example
 
- 
				        # above some tables names are identified as keywords...
 
- 
				        elif item.ttype is Keyword:
 
- 
				            yield item.value
 
- 
				
 
- 
				def extract_tables(p_sqltext):
 
- 
				    stream = extract_from_part(sqlparse.parse(p_sqltext)[0])
 
- 
				    return list(extract_table_identifiers(stream))
 
- 
				
 
- 
				def f_find_in_list(myList,value):
 
- 
				    try: 
 
- 
				        for v in range(0,len(myList)): 
 
- 
				            if value==myList[v]: 
 
- 
				                return 1
 
- 
				        return 0
 
- 
				    except: 
 
- 
				        return 0
 
- 
				
 
- 
				def f_get_parm(p_dbinfo):
 
- 
				    conn = MySQLdb.connect(host=p_dbinfo[0], user=p_dbinfo[1], passwd=p_dbinfo[2],db=p_dbinfo[3])
 
- 
				    cursor = conn.cursor()
 
- 
				    cursor.execute("select lower(variable_name),variable_value from performance_schema.global_variables where upper(variable_name) in ('"+"','".join(list(SYS_PARM_FILTER))+"') order by variable_name")
 
- 
				    records = cursor.fetchall()
 
- 
				    cursor.close()
 
- 
				    conn.close()
 
- 
				    return records
 
- 
				
 
- 
				def f_print_parm(p_parm_result):
 
- 
				    print "===== SYSTEM PARAMETER ====="
 
- 
				    status_title=('parameter_name','value')
 
- 
				    print "+--------------------------------+------------------------------------------------------------+"
 
- 
				    print seq3,status_title[0].center(30),
 
- 
				    print seq3,status_title[1].center(58),seq3
 
- 
				    print "+--------------------------------+------------------------------------------------------------+"
 
- 
				
 
- 
				    for row in p_parm_result:
 
- 
				    print seq3,row[0].ljust(30),
 
- 
				        if 'size' in row[0]:
 
- 
				            if string.atoi(row[1])>=1024*1024*1024:
 
- 
				                print seq3,(str(round(string.atoi(row[1])/1024/1024/1024,2))+' G').rjust(58),seq3
 
- 
				            elif string.atoi(row[1])>=1024*1024:
 
- 
				                print seq3,(str(round(string.atoi(row[1])/1024/1024,2))+' M').rjust(58),seq3
 
- 
				            elif string.atoi(row[1])>=1024:
 
- 
				                print seq3,(str(round(string.atoi(row[1])/1024,2))+' K').rjust(58),seq3
 
- 
				            else:
 
- 
				                print seq3,(row[1]+' B').rjust(58),seq3
 
- 
				        else:
 
- 
				            print seq3,row[1].rjust(58),seq3
 
- 
				    print "+--------------------------------+------------------------------------------------------------+"
 
- 
				    print
 
- 
				
 
- 
				def f_print_optimizer_switch(p_dbinfo):
 
- 
				    print "===== OPTIMIZER SWITCH ====="
 
- 
				    db = MySQLdb.connect(host=p_dbinfo[0], user=p_dbinfo[1], passwd=p_dbinfo[2],db=p_dbinfo[3])
 
- 
				    cursor = db.cursor()
 
- 
				    cursor.execute("select variable_value from performance_schema.global_variables where upper(variable_name)='OPTIMIZER_SWITCH'")
 
- 
				    rows = cursor.fetchall()
 
- 
				    print "+------------------------------------------+------------+"
 
- 
				    print seq3,'switch_name'.center(40),
 
- 
				    print seq3,'value'.center(10),seq3
 
- 
				    print "+------------------------------------------+------------+"
 
- 
				    for row in rows[0][0].split(','):
 
- 
				        print seq3,row.split('=')[0].ljust(40),
 
- 
				        print seq3,row.split('=')[1].rjust(10),seq3
 
- 
				    print "+------------------------------------------+------------+"
 
- 
				    cursor.close()
 
- 
				    db.close()
 
- 
				    print
 
- 
				
 
- 
				def f_exec_sql(p_dbinfo,p_sqltext,p_option):
 
- 
				    results={}
 
- 
				    conn = MySQLdb.connect(host=p_dbinfo[0], user=p_dbinfo[1], passwd=p_dbinfo[2],db=p_dbinfo[3])
 
- 
				    cursor = conn.cursor()
 
- 
				
 
- 
				    if f_find_in_list(p_option,'PROFILING'):
 
- 
				        cursor.execute("set profiling=1")
 
- 
				        cursor.execute("select ifnull(max(query_id),0) from INFORMATION_SCHEMA.PROFILING")
 
- 
				        records = cursor.fetchall()
 
- 
				        query_id=records[0][0] +2   #skip next sql
 
- 
				
 
- 
				    if f_find_in_list(p_option,'STATUS'):
 
- 
				        #cursor.execute("select concat(upper(left(variable_name,1)),substring(lower(variable_name),2,(length(variable_name)-1))) var_name,variable_value var_value from performance_schema.session_status where variable_name in('"+"','".join(tuple(SES_STATUS_ITEM))+"') order by 1")
 
- 
				        cursor.execute("select concat(upper(left(variable_name,1)),substring(lower(variable_name),2,(length(variable_name)-1))) var_name,variable_value var_value from performance_schema.session_status order by 1")
 
- 
				        records = cursor.fetchall()
 
- 
				        results['BEFORE_STATUS']=dict(records)
 
- 
				
 
- 
				    cursor.execute(p_sqltext)
 
- 
				
 
- 
				    if f_find_in_list(p_option,'STATUS'):
 
- 
				        cursor.execute("select concat(upper(left(variable_name,1)),substring(lower(variable_name),2,(length(variable_name)-1))) var_name,variable_value var_value from performance_schema.session_status order by 1")
 
- 
				        records = cursor.fetchall()
 
- 
				        results['AFTER_STATUS']=dict(records)
 
- 
				
 
- 
				    if f_find_in_list(p_option,'PROFILING'):
 
- 
				        cursor.execute("select STATE,DURATION,CPU_USER,CPU_SYSTEM,BLOCK_OPS_IN,BLOCK_OPS_OUT ,MESSAGES_SENT ,MESSAGES_RECEIVED ,PAGE_FAULTS_MAJOR ,PAGE_FAULTS_MINOR ,SWAPS from INFORMATION_SCHEMA.PROFILING where query_id="+str(query_id)+" order by seq")
 
- 
				        records = cursor.fetchall()
 
- 
				        results['PROFILING_DETAIL']=records
 
- 
				
 
- 
				        cursor.execute("SELECT STATE,SUM(DURATION) AS Total_R,ROUND(100*SUM(DURATION)/(SELECT SUM(DURATION) FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID="+str(query_id)+"),2) AS Pct_R,COUNT(*) AS Calls,SUM(DURATION)/COUNT(*) AS R_Call FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID="+str(query_id)+" GROUP BY STATE ORDER BY Total_R DESC")
 
- 
				        records = cursor.fetchall()
 
- 
				        results['PROFILING_SUMMARY']=records
 
- 
				
 
- 
				    cursor.close()
 
- 
				    conn.close()
 
- 
				    return results
 
- 
				
 
- 
				def f_print_status(p_before_status,p_after_status):
 
- 
				    print "===== SESSION STATUS (DIFFERENT) ====="
 
- 
				    status_title=('status_name','before','after','diff')
 
- 
				    print "+-------------------------------------+-----------------+-----------------+-----------------+"
 
- 
				    print seq3,status_title[0].center(35),
 
- 
				    print seq3,status_title[1].center(15),
 
- 
				    print seq3,status_title[2].center(15),
 
- 
				    print seq3,status_title[3].center(15),seq3
 
- 
				    print "+-------------------------------------+-----------------+-----------------+-----------------+"
 
- 
				
 
- 
				    for key in sorted(p_before_status.keys()):
 
- 
				        if p_before_status[key]<>p_after_status[key]:
 
- 
				            print seq3,key.ljust(35),
 
- 
				            print seq3,p_before_status[key].rjust(15),
 
- 
				            print seq3,p_after_status[key].rjust(15),
 
- 
				            print seq3,str(float(p_after_status[key])-float(p_before_status[key])).rjust(15),seq3
 
- 
				    print "+-------------------------------------+-----------------+-----------------+-----------------+"
 
- 
				    print
 
- 
				
 
- 
				def f_print_time(p_starttime,p_endtime):
 
- 
				    print "===== EXECUTE TIME ====="
 
- 
				    print timediff(p_starttime,p_endtime)
 
- 
				    print
 
- 
				
 
- 
				
 
- 
				def f_print_profiling(p_profiling_detail,p_profiling_summary):
 
- 
				    print "===== SQL PROFILING(DETAIL)====="
 
- 
				    status_title=('state','duration','cpu_user','cpu_sys','bk_in','bk_out','msg_s','msg_r','p_f_ma','p_f_mi','swaps')
 
- 
				    print "+--------------------------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+"
 
- 
				    print seq3,status_title[0].center(30),
 
- 
				    print seq3,status_title[1].center(8),
 
- 
				    print seq3,status_title[2].center(8),
 
- 
				    print seq3,status_title[3].center(8),
 
- 
				    print seq3,status_title[4].center(8),
 
- 
				    print seq3,status_title[5].center(8),
 
- 
				    print seq3,status_title[6].center(8),
 
- 
				    print seq3,status_title[7].center(8),
 
- 
				    print seq3,status_title[8].center(8),
 
- 
				    print seq3,status_title[9].center(8),
 
- 
				    print seq3,status_title[10].center(8),seq3
 
- 
				    print "+--------------------------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+"
 
- 
				
 
- 
				    for row in p_profiling_detail:
 
- 
				        print seq3,row[0].ljust(30),
 
- 
				        print seq3,str(row[1]).rjust(8),
 
- 
				        print seq3,str(row[2]).rjust(8),
 
- 
				        print seq3,str(row[3]).rjust(8),
 
- 
				        print seq3,str(row[4]).rjust(8),
 
- 
				        print seq3,str(row[5]).rjust(8),
 
- 
				        print seq3,str(row[6]).rjust(8),
 
- 
				        print seq3,str(row[7]).rjust(8),
 
- 
				        print seq3,str(row[8]).rjust(8),
 
- 
				        print seq3,str(row[9]).rjust(8),
 
- 
				        print seq3,str(row[10]).rjust(8),seq3
 
- 
				    print "+--------------------------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+"
 
- 
				    print 'bk_in: block_ops_in'
 
- 
				    print 'bk_out: block_ops_out'
 
- 
				    print 'msg_s: message sent'
 
- 
				    print 'msg_r: message received'
 
- 
				    print 'p_f_ma: page_faults_major'
 
- 
				    print 'p_f_mi: page_faults_minor'
 
- 
				    print
 
- 
				
 
- 
				    print "===== SQL PROFILING(SUMMARY)====="
 
- 
				    status_title=('state','total_r','pct_r','calls','r/call')
 
- 
				    print "+-------------------------------------+-----------------+------------+-------+-----------------+"
 
- 
				    print seq3,status_title[0].center(35),
 
- 
				    print seq3,status_title[1].center(15),
 
- 
				    print seq3,status_title[2].center(10),
 
- 
				    print seq3,status_title[3].center(5),
 
- 
				    print seq3,status_title[4].center(15),seq3
 
- 
				    print "+-------------------------------------+-----------------+------------+-------+-----------------+"
 
- 
				
 
- 
				    for row in p_profiling_summary:
 
- 
				        print seq3,row[0].ljust(35),
 
- 
				        print seq3,str(row[1]).rjust(15),
 
- 
				        print seq3,str(row[2]).rjust(10),
 
- 
				        print seq3,str(row[3]).rjust(5),
 
- 
				        print seq3,str(row[4]).rjust(15),seq3
 
- 
				    print "+-------------------------------------+-----------------+------------+-------+-----------------+"
 
- 
				    print
 
- 
				
 
- 
				def f_get_sqlplan(p_dbinfo,p_sqltext):
 
- 
				    results={}
 
- 
				
 
- 
				    db = MySQLdb.connect(host=p_dbinfo[0], user=p_dbinfo[1], passwd=p_dbinfo[2],db=p_dbinfo[3])
 
- 
				    cursor = db.cursor()
 
- 
				    cursor.execute("explain extended "+p_sqltext)
 
- 
				    records = cursor.fetchall()
 
- 
				    results['SQLPLAN']=records
 
- 
				    cursor.execute("show warnings")
 
- 
				    records = cursor.fetchall()
 
- 
				    results['WARNING']=records
 
- 
				    cursor.close()
 
- 
				    db.close()
 
- 
				    return results
 
- 
				
 
- 
				def f_print_sqlplan(p_sqlplan,p_warning):
 
- 
				    plan_title=('id','select_type','table','partitions','type','possible_keys','key','key_len','ref','rows','filtered','Extra')
 
- 
				
 
- 
				    print "===== SQL PLAN ====="
 
- 
				    print "+--------+------------------+------------+------------+------------+---------------+------------+------------+------------+------------+------------+------------+"
 
- 
				    print seq3,plan_title[0].center(6),
 
- 
				    print seq3,plan_title[1].center(16),
 
- 
				    print seq3,plan_title[2].center(10),
 
- 
				    print seq3,plan_title[3].center(10),
 
- 
				    print seq3,plan_title[4].center(10),
 
- 
				    print seq3,plan_title[5].center(10),
 
- 
				    print seq3,plan_title[6].center(10),
 
- 
				    print seq3,plan_title[7].center(10),
 
- 
				    print seq3,plan_title[8].center(10),
 
- 
				    print seq3,plan_title[9].center(10),
 
- 
				    print seq3,plan_title[10].center(10),
 
- 
				    print seq3,plan_title[11].center(10),seq3
 
- 
				    print "+--------+------------------+------------+------------+------------+---------------+------------+------------+------------+------------+------------+------------+"
 
- 
				    for row in p_sqlplan:
 
- 
				        print seq3,str(row[0]).rjust(6),                # id
 
- 
				        print seq3,row[1].ljust(16),                    # select_type
 
- 
				        #print seq3,row[2].ljust(10),                    # table
 
- 
				        if not "NonyType" in str(type(row[2])):
 
- 
				            print seq3,row[2].ljust(10),
 
- 
				        else:
 
- 
				            print seq3,"NULL".ljust(10),
 
- 
				        
 
- 
				        if not "NoneType" in str(type(row[3])):         #partitions
 
- 
				            print seq3,row[3].ljust(10),
 
- 
				        else:
 
- 
				            print seq3,"NULL".ljust(10), 
 
- 
				                              
 
- 
				        #print seq3,row[3].ljust(10), 
 
- 
				        if not "NoneType" in str(type(row[4])): #type
 
- 
				            print seq3,row[4].ljust(10),
 
- 
				        else:
 
- 
				            print seq3,"NULL".ljust(10), 
 
- 
				        
 
- 
				        if not "NoneType" in str(type(row[5])):         # possible_keys
 
- 
				            print seq3,row[5].ljust(13),
 
- 
				        else:
 
- 
				            print seq3,"NULL".ljust(13),
 
- 
				
 
- 
				        if not "NoneType" in str(type(row[6])):         # key
 
- 
				            print seq3,row[6].ljust(10), 
 
- 
				        else:
 
- 
				            print seq3,"NULL".ljust(10),
 
- 
				        
 
- 
				        if not "NoneType" in str(type(row[7])):         # key_len
 
- 
				            print seq3,row[7].ljust(10), 
 
- 
				        else:
 
- 
				            print seq3,"NULL".ljust(10),
 
- 
				
 
- 
				        if not "NoneType" in str(type(row[8])):         # ref
 
- 
				            print seq3,row[8].ljust(10), 
 
- 
				        else:
 
- 
				            print seq3,"NULL".ljust(10),
 
- 
				
 
- 
				        print seq3,str(row[9]).rjust(10),               # rows
 
- 
				
 
- 
				        print seq3,str(row[10]).rjust(10),               # filters
 
- 
				
 
- 
				        if not "NoneType" in str(type(row[11])):        # Extra
 
- 
				            print seq3,row[11].ljust(10), 
 
- 
				        else:
 
- 
				            print seq3,"NULL".ljust(10),
 
- 
				        print seq3
 
- 
				
 
- 
				    print "+--------+------------------+------------+------------+------------+---------------+------------+------------+------------+------------+------------+------------+"
 
- 
				    print
 
- 
				
 
- 
				    print "===== OPTIMIZER REWRITE SQL ====="
 
- 
				    for row in p_warning:
 
- 
				        print sqlparse.format(row[2],reindent=True, keyword_case='upper',strip_comments=True)
 
- 
				    print
 
- 
				
 
- 
				def f_get_table(p_dbinfo,p_sqltext):
 
- 
				    r_tables=[]
 
- 
				    db = MySQLdb.connect(host=p_dbinfo[0], user=p_dbinfo[1], passwd=p_dbinfo[2],db=p_dbinfo[3])
 
- 
				    cursor = db.cursor()
 
- 
				    cursor.execute("explain "+p_sqltext)
 
- 
				    rows = cursor.fetchall ()
 
- 
				    for row in rows:
 
- 
				        table_name = row[2]
 
- 
				        if '<' in table_name:
 
- 
				            continue
 
- 
				        if len(r_tables)==0:
 
- 
				            r_tables.append(table_name)
 
- 
				        elif f_find_in_list(r_tables,table_name) == -1:
 
- 
				            r_tables.append(table_name)
 
- 
				    cursor.close()
 
- 
				    db.close()
 
- 
				    return r_tables
 
- 
				
 
- 
				def f_print_tableinfo(p_dbinfo,p_tablename):
 
- 
				    plan_title=('table_name','engine','format','table_rows','avg_row','total_mb','data_mb','index_mb')
 
- 
				    db = MySQLdb.connect(host=p_dbinfo[0], user=p_dbinfo[1], passwd=p_dbinfo[2],db=p_dbinfo[3])
 
- 
				    cursor = db.cursor()
 
- 
				    stmt = "select engine,row_format as format,table_rows,avg_row_length as avg_row,round((data_length+index_length)/1024/1024,2) as total_mb,round((data_length)/1024/1024,2) as data_mb,round((index_length)/1024/1024,2) as index_mb from information_schema.tables where table_schema='"+p_dbinfo[3]+"' and table_name='"+p_tablename+"'"
 
- 
				    cursor.execute(stmt)
 
- 
				    rows = cursor.fetchall ()
 
- 
				    print "+-----------------+------------+------------+------------+------------+------------+------------+------------+"
 
- 
				    print seq3,plan_title[0].center(15),
 
- 
				    print seq3,plan_title[1].center(10),
 
- 
				    print seq3,plan_title[2].center(10),
 
- 
				    print seq3,plan_title[3].center(10),
 
- 
				    print seq3,plan_title[4].center(10),
 
- 
				    print seq3,plan_title[5].center(10),
 
- 
				    print seq3,plan_title[6].center(10),
 
- 
				    print seq3,plan_title[7].center(10),seq3
 
- 
				    print "+-----------------+------------+------------+------------+------------+------------+------------+------------+"
 
- 
				    for row in rows:
 
- 
				        print seq3,p_tablename.ljust(15),
 
- 
				        print seq3,row[0].ljust(10),
 
- 
				        print seq3,row[1].ljust(10), 
 
- 
				        print seq3,str(row[2]).rjust(10), 
 
- 
				        print seq3,str(row[3]).rjust(10),
 
- 
				        print seq3,str(row[4]).rjust(10), 
 
- 
				        print seq3,str(row[5]).rjust(10), 
 
- 
				        print seq3,str(row[6]).rjust(10),seq3
 
- 
				    print "+-----------------+------------+------------+------------+------------+------------+------------+------------+"
 
- 
				    cursor.close()
 
- 
				    db.close()
 
- 
				
 
- 
				def f_print_indexinfo(p_dbinfo,p_tablename):
 
- 
				    plan_title=('index_name','non_unique','seq_in_index','column_name','collation','cardinality','nullable','index_type')
 
- 
				    db = MySQLdb.connect(host=p_dbinfo[0], user=p_dbinfo[1], passwd=p_dbinfo[2],db=p_dbinfo[3])
 
- 
				    cursor = db.cursor()
 
- 
				    stmt = "select index_name,non_unique,seq_in_index,column_name,collation,cardinality,nullable,index_type from information_schema.statistics where table_schema='"+p_dbinfo[3]+"' and table_name='"+p_tablename+"' order by 1,3"
 
- 
				    cursor.execute(stmt)
 
- 
				    rows = cursor.fetchall ()
 
- 
				    if len(rows)>0:
 
- 
				        print "+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+"
 
- 
				        print seq3,plan_title[0].center(15),
 
- 
				        print seq3,plan_title[1].center(15),
 
- 
				        print seq3,plan_title[2].center(15),
 
- 
				        print seq3,plan_title[3].center(15),
 
- 
				        print seq3,plan_title[4].center(15),
 
- 
				        print seq3,plan_title[5].center(15),
 
- 
				        print seq3,plan_title[6].center(15),
 
- 
				        print seq3,plan_title[7].center(15),seq3
 
- 
				        print "+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+"
 
- 
				        for row in rows:
 
- 
				            print seq3,row[0].ljust(15),
 
- 
				            print seq3,str(row[1]).rjust(15),
 
- 
				            print seq3,str(row[2]).rjust(15),
 
- 
				            print seq3,str(row[3]).rjust(15),
 
- 
				            print seq3,str(row[4]).rjust(15),
 
- 
				            print seq3,str(row[5]).rjust(15),
 
- 
				            print seq3,str(row[6]).rjust(15),
 
- 
				            print seq3,str(row[7]).rjust(15),seq3
 
- 
				        print "+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+"
 
- 
				    cursor.close()
 
- 
				    db.close()
 
- 
				
 
- 
				def f_get_mysql_version(p_dbinfo):
 
- 
				    db = MySQLdb.connect(host=p_dbinfo[0], user=p_dbinfo[1], passwd=p_dbinfo[2],db=p_dbinfo[3])
 
- 
				    cursor = db.cursor()
 
- 
				    cursor.execute("select @@version")
 
- 
				    records = cursor.fetchall ()
 
- 
				    cursor.close()
 
- 
				    db.close()
 
- 
				    return records[0][0]
 
- 
				
 
- 
				def f_print_title(p_dbinfo,p_mysql_version,p_sqltext):
 
- 
				    print '*'*100
 
- 
				    print '*','MySQL SQL Tuning Tools v1.0 for mysql5.7(created by hanfeng modified by ycc)'.center(96),'*'
 
- 
				    print '*'*100
 
- 
				
 
- 
				    print 
 
- 
				    print "===== BASIC INFORMATION ====="
 
- 
				    title=('server_ip','user_name','db_name','db_version')
 
- 
				    print "+----------------------+------------+------------+------------+"
 
- 
				    print seq3,title[0].center(20),
 
- 
				    print seq3,title[1].center(10),
 
- 
				    print seq3,title[2].center(10),
 
- 
				    print seq3,title[3].center(10),seq3
 
- 
				    print "+----------------------+------------+------------+------------+"
 
- 
				    print seq3,p_dbinfo[0].center(20),
 
- 
				    print seq3,p_dbinfo[1].center(10),
 
- 
				    print seq3,p_dbinfo[3].center(10),
 
- 
				    print seq3,p_mysql_version.center(10),seq3
 
- 
				    print "+----------------------+------------+------------+------------+"
 
- 
				    print
 
- 
				    print "===== ORIGINAL SQL TEXT ====="
 
- 
				    print sqlparse.format(p_sqltext,reindent=True, keyword_case='upper')
 
- 
				    print
 
- 
				
 
- 
				'''
 
- 
				def f_print_table(p_value,p_option): #p_option "(key-n => title,max_len,align_value)"
 
- 
				    for k in p_option.keys():
 
- 
				        v = p_option[k]
 
- 
				        print "+",
 
- 
				        print int(v.split(',')[1])*"-",
 
- 
				    print "+"
 
- 
				    
 
- 
				    for k in p_option.keys():
 
- 
				        v = p_option[k]
 
- 
				        print "|",
 
- 
				        print v.split(',')[0].center(int(v.split(',')[0])-2),
 
- 
				    print "|",
 
- 
				
 
- 
				    for k in p_option.keys():
 
- 
				        v = p_option[k]
 
- 
				        print "+",
 
- 
				        print int(v.split(',')[1])*"-",
 
- 
				    print "+"
 
- 
				
 
- 
				    for row in p_value:
 
- 
				        k=0
 
- 
				        for col in row:
 
- 
				            k+=1
 
- 
				            print "|",
 
- 
				            if p_option[k].split(',')[2]=='l':
 
- 
				                print col.ljust(p_option[k].split(',')[1]),
 
- 
				            elif p_option[k].split(',')[2]=='r':
 
- 
				                print col.rjust(p_option[k].split(',')[1]),
 
- 
				            else
 
- 
				                print col.center(p_option[k].split(',')[1]),
 
- 
				            print "|",
 
- 
				
 
- 
				    for k in p_option.keys():
 
- 
				        v = p_option[k]
 
- 
				        print "+",
 
- 
				        print int(v.split(',')[1])*"-",
 
- 
				    print "+"
 
- 
				'''
 
- 
				
 
- 
				def timediff(timestart, timestop):
 
- 
				        t  = (timestop-timestart)
 
- 
				        time_day = t.days
 
- 
				        s_time = t.seconds
 
- 
				        ms_time = t.microseconds / 1000000
 
- 
				        usedtime = int(s_time + ms_time)
 
- 
				        time_hour = usedtime / 60 / 60
 
- 
				        time_minute = (usedtime - time_hour * 3600 ) / 60
 
- 
				        time_second =  usedtime - time_hour * 3600 - time_minute * 60
 
- 
				        time_micsecond = (t.microseconds - t.microseconds / 1000000) / 1000
 
- 
				
 
- 
				        retstr = "%d day %d hour %d minute %d second %d microsecond "  %(time_day, time_hour, time_minute, time_second, time_micsecond)
 
- 
				        return retstr
 
- 
				
 
- 
				if __name__=="__main__":
 
- 
				    dbinfo=["","","",""]  #dbhost,dbuser,dbpwd,dbname
 
- 
				    sqltext=""
 
- 
				    option=[]
 
- 
				    config_file=""
 
- 
				    mysql_version=""
 
- 
				
 
- 
				    opts, args = getopt.getopt(sys.argv[1:], "p:s:")
 
- 
				    for o,v in opts:
 
- 
				        if o == "-p":
 
- 
				            config_file = v
 
- 
				        elif o == "-s":
 
- 
				            sqltext = v
 
- 
				
 
- 
				    config = ConfigParser.ConfigParser()
 
- 
				    config.readfp(open(config_file,"rb"))
 
- 
				    dbinfo[0] = config.get("database","server_ip")
 
- 
				    dbinfo[1] = config.get("database","db_user")
 
- 
				    dbinfo[2] = config.get("database","db_pwd")
 
- 
				    dbinfo[3] = config.get("database","db_name")
 
- 
				
 
- 
				    mysql_version = f_get_mysql_version(dbinfo)
 
- 
				    
 
- 
				    f_print_title(dbinfo,mysql_version,sqltext)
 
- 
				
 
- 
				    if config.get("option","sys_parm")=='ON':
 
- 
				        parm_result = f_get_parm(dbinfo)
 
- 
				        f_print_parm(parm_result)
 
- 
				        f_print_optimizer_switch(dbinfo)
 
- 
				
 
- 
				    if config.get("option","sql_plan")=='ON':
 
- 
				        sqlplan_result = f_get_sqlplan(dbinfo,sqltext)
 
- 
				        f_print_sqlplan(sqlplan_result['SQLPLAN'],sqlplan_result['WARNING'])
 
- 
				
 
- 
				    if config.get("option","obj_stat")=='ON':
 
- 
				        print "===== OBJECT STATISTICS ====="
 
- 
				        for table_name in extract_tables(sqltext):
 
- 
				            f_print_tableinfo(dbinfo,table_name)
 
- 
				            f_print_indexinfo(dbinfo,table_name)
 
- 
				        print
 
- 
				
 
- 
				    if config.get("option","ses_status")=='ON':
 
- 
				        option.append('STATUS')
 
- 
				
 
- 
				    if config.get("option","sql_profile")=='ON':
 
- 
				        option.append('PROFILING')
 
- 
				
 
- 
				    if config.get("option","ses_status")=='ON' or config.get("option","sql_profile")=='ON':
 
- 
				        starttime = datetime.datetime.now()
 
- 
				        exec_result = f_exec_sql(dbinfo,sqltext,option)
 
- 
				        endtime = datetime.datetime.now()
 
- 
				
 
- 
				        if config.get("option","ses_status")=='ON':
 
- 
				            f_print_status(exec_result['BEFORE_STATUS'],exec_result['AFTER_STATUS'])
 
- 
				
 
- 
				        if config.get("option","sql_profile")=='ON':
 
- f_print_profiling(exec_result['PROFILING_DETAIL'],exec_result['PROFILING_SUMMARY
网站名称:mysql的性能优化工具(源自韩锋大师,针对5.7修改)
文章地址:http://www.cqwzjz.cn/article/ghjpds.html

 建站
建站
 咨询
咨询 售后
售后
 建站咨询
建站咨询 
 