一、需求分析
线上的MySQL服务器,最近有很多慢查询。需要统计出行数大于100万的表,进行统一优化。
需要筛选出符合条件的表,统计到excel中,格式如下:
库名 | 表名 | 行数 |
db1 | users | 1234567 |
二、统计表的行数
统计表的行数,有2中方法:
1. 通过查询mysql的information_schema数据库中INFODB_SYS_TABLESTATS表,它记录了innodb类型每个表大致的数据行数
2. select count(1) from 库名.表名
下面来分析一下这2种方案。
第一种方案,不是精确记录的。虽然效率快,但是表会有遗漏!
第二钟方案,才是准确的。虽然慢,但是表不会遗漏。
备注:
count(1)其实这个1,并不是表示第一个字段,而是表示一个固定值。
count(1),其实就是计算一共有多少符合条件的行。
1并不是表示第一个字段,而是表示一个固定值。
其实就可以想成表中有这么一个字段,这个字段就是固定值1,count(1),就是计算一共有多少个1.
写入json文件
下面这段代码,是参考我之前写的一篇文章:
https://www.cnblogs.com/xiao987334176/p/9901692.html
在此基础上,做了部分修改,完整代码如下:
#!/usr/bin/env python3 # coding: utf-8 import pymysql import json conn = pymysql.connect( host="192.168.91.128", # mysql ip地址 user="root", passwd="root", port=3306, # mysql 端口号,注意:必须是int类型 connect_timeout = 3 # 超时时间 ) cur = conn.cursor() # 创建游标 # 获取mysql中所有数据库 cur.execute('SHOW DATABASES') data_all = cur.fetchall() # 获取执行的返回结果 # print(data_all) dic = {} # 大字典,第一层 for i in data_all: if i[0] not in dic: # 判断库名不在dic中时 # 排序列表,排除mysql自带的数据库 exclude_list = ["sys", "information_schema", "mysql", "performance_schema"] if i[0] not in exclude_list: # 判断不在列表中时 # 写入第二层数据 dic[i[0]] = {'name': i[0], 'table_list': []} conn.select_db(i[0]) # 切换到指定的库中 cur.execute('SHOW TABLES') # 查看库中所有的表 ret = cur.fetchall() # 获取执行结果 for j in ret: # 查询表的行数 cur.execute('select count(1) from `%s`;'% j[0]) ret = cur.fetchall() # print(ret) for k in ret: print({'tname': j[0], 'rows': k[0]}) dic[i[0]]['table_list'].append({'tname': j[0], 'rows': k[0]}) with open('tj.json','w',encoding='utf-8') as f: f.write(json.dumps(dic))
三、写入excel中
直接读取tj.json文件,进行写入,完整代码如下:
#!/usr/bin/env python3 # coding: utf-8 import xlwt import json from collections import OrderedDict f = xlwt.Workbook() sheet1 = f.add_sheet('统计', cell_overwrite_ok=True) row0 = ["库名", "表名", "行数"] # 写第一行 for i in range(0, len(row0)): sheet1.write(0, i, row0[i]) # 加载json文件 with open("tj.json", 'r') as load_f: load_dict = json.load(load_f) # 反序列化文件 order_dic = OrderedDict() # 有序字典 for key in sorted(load_dict): # 先对普通字典key做排序 order_dic[key] = load_dict[key] # 再写入key num = 0 # 计数器 for i in order_dic: # 遍历所有表 for j in order_dic[i]["table_list"]: # 判断行数大于100万时 if j['rows'] > 1000000: # 写入库名 sheet1.write(num + 1, 0, i) # 写入表名 sheet1.write(num + 1, 1, j['tname']) # 写入行数 sheet1.write(num + 1, 2, j['rows']) num += 1 # 自增1 f.save('test1.xls')
执行程序,打开excel文件,效果如下: