homework-jianmu/tests/pytest/query/query_performance.py

220 lines
7.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import time
import taos
import csv
import numpy as np
import random
import os
import requests
import json
import sys
"""
需要第三方库: taos,requests,numpy
当前机器已经启动taosd服务
使用方法见底部示例
"""
class Ding:
"""
发送消息到钉钉,
urls: 钉钉群的token组成的list可以发多个钉钉群需要提前加白名单或其他放行策略
at_mobiles 需要@的人的手机号组成的list
msg 要发送的str
"""
def __init__(self, url_list, at_mobiles):
self.urls = url_list
self.at_mobiles = at_mobiles
def send_message(self, msg):
data1 = {
"msgtype": "text",
"text": {
"content": msg
},
"at": {
"atMobiles": self.at_mobiles,
"isAtAll": False
}
}
header = {'Content-Type': 'application/json; charset=utf-8'}
for url in self.urls:
requests.post(url=url, data=json.dumps(data1), headers=header)
class TDConn:
def __init__(self, config:dict):
self.host = config['host']
self.user = config['user']
self.password = config['password']
self.config = config['config']
self.conn = None
self.cursor = None
def connect(self):
conn = taos.connect(host=self.host, user=self.user, password=self.password, config=self.config)
cursor = conn.cursor()
self.conn = conn
self.cursor = cursor
print('connect ...')
return self.cursor
def close(self):
self.cursor.close()
self.conn.close()
print('close ... ')
class Tool:
"""
可能有用
"""
@staticmethod
def str_gen(num):
return ''.join(random.sample('abcdefghijklmnopqrstuvwxyz', num))
@staticmethod
def float_gen(n, m):
return random.uniform(n, m)
@staticmethod
def int_gen(n, m):
return random.randint(n, m)
class Demo:
def __init__(self, engine):
self.engine = engine['engine'](engine['config'])
self.cursor = self.engine.connect()
def date_gen(self, db, number_per_table, type_of_cols, num_of_cols_per_record, num_of_tables):
"""
:目前都是 taosdemo 的参数
:return:
"""
sql = 'yes | sudo taosdemo -d {db} -n {number_per_table} -b {type_of_cols} -l {num_of_cols_per_record} ' \
'-t {num_of_tables}'.format(db=db, number_per_table=number_per_table, type_of_cols=type_of_cols,
num_of_cols_per_record=num_of_cols_per_record, num_of_tables=num_of_tables)
os.system(sql)
print('insert data completed')
# def main(self, db, circle, csv_name, case_func, result_csv, nums, ding_flag):
def main(self, every_num_per_table, result_csv, all_result_csv, values):
db = values['db_name']
number_per_table = every_num_per_table
type_of_cols = values['col_type']
num_of_cols_per_record = values['col_num']
num_of_tables = values['table_num']
self.date_gen(db=db, number_per_table=number_per_table, type_of_cols=type_of_cols,
num_of_cols_per_record=num_of_cols_per_record, num_of_tables=num_of_tables)
circle = values['circle']
# print(every_num_per_table, result_csv, values)
csv_name = result_csv
case_func = values['sql_func']
nums = num_of_tables * number_per_table
ding_flag = values['ding_flag']
_data = []
f = open(csv_name,'w',encoding='utf-8')
f1 = open(all_result_csv,'a',encoding='utf-8')
csv_writer = csv.writer(f)
csv_writer1 = csv.writer(f1)
csv_writer.writerow(["number", "elapse", 'sql'])
self.cursor.execute('use {db};'.format(db=db))
for i in range(circle):
self.cursor.execute('reset query cache;')
sql = case_func()
start = time.time()
self.cursor.execute(sql)
self.cursor.fetchall()
end = time.time()
_data.append(end-start)
elapse = '%.4f' %(end -start)
print(sql, i, elapse, '\n')
csv_writer.writerow([i+1, elapse, sql])
# time.sleep(1)
_list = [nums, np.mean(_data)]
_str = '总数据: %s 条 , table数: %s , 每个table数据数: %s , 数据类型: %s \n' % \
(nums, num_of_tables, number_per_table, type_of_cols)
# print('avg : ', np.mean(_data), '\n')
_str += '平均值 : %.4f\n' % np.mean(_data)
for each in (50, 80, 90, 95):
_list.append(np.percentile(_data,each))
_str += ' %d 分位数 : %.4f\n' % (each , np.percentile(_data,each))
print(_str)
if ding_flag:
ding = Ding(values['ding_config']['urls'], values['ding_config']['at_mobiles'])
ding.send_message(_str)
csv_writer1.writerow(_list)
f.close()
f1.close()
self.engine.close()
def run(engine, test_cases: dict, result_dir):
for each_case, values in test_cases.items():
for every_num_per_table in values['number_per_table']:
result_csv = result_dir + '{case}_table{table_num}_{number_per_table}.csv'.\
format(case=each_case, table_num=values['table_num'], number_per_table=every_num_per_table)
all_result_csv = result_dir + '{case_all}_result.csv'.format(case_all=each_case)
d = Demo(engine)
# print(each_case, result_csv)
d.main(every_num_per_table, result_csv, all_result_csv, values)
if __name__ == '__main__':
"""
测试用例在test_cases中添加。
result_dir 报告生成目录,会生成每次测试结果,和具体某一用例的统计结果.需注意目录权限需要执行用户可写。
case1、case2 : 具体用例名称
engine: 数据库引擎目前只有taosd。使用时需开启taosd服务。
table_num: 造数据时的table数目
circle: 循环测试次数,求平均值
number_per_table需要传list多个数值代表会按照list内的数值逐个测试
col_numtable col的数目
col_type 表中数据类型
db_name 造数据的db名默认用test
sql_func 当前测试的sql方法需要自己定义
ding_flag 如果需要钉钉发送数据flag设置真值
ding_config 如ding_flag 设置为真值此项才有意义。ding_flag为假时此项可以为空。urls传入一list内容为要发送的群的token
需提前设置白名单at_mobiles传入一list内容为在群内需要@的人的手机号
"""
engine_dict = {
'taosd': {'engine': TDConn, 'config':
{'host': '127.0.0.1', 'user': 'root', 'password': 'taosdata', 'config':'/etc/taos'}}
}
def case1():
return 'select * from meters where f1 = {n};'.format(n=random.randint(1,30))
def case2():
return 'select * from meters where f1 = %.4f;' %random.uniform(1,30)
result_dir = '/usr/local/demo/benchmarktestdata/'
test_cases = {
'case1': {'engine':'taosd', 'table_num': 10, 'circle': 100, 'number_per_table':[10, 100], 'col_num': 5,
'col_type': 'INT', 'db_name': 'test', 'sql_func': case1, 'ding_flag': True,
'ding_config':
{'urls': [r'https://oapi.dingtalk.com/robot/send?access_token=xxxxxxx0cd93'],
'at_mobiles':[17000000000,],}},
'case2': {'engine':'taosd', 'table_num': 10, 'circle': 50, 'number_per_table':[10, 100], 'col_num': 5,
'col_type': 'FLOAT', 'db_name': 'test', 'sql_func': case2, 'ding_flag': False,
'ding_config': None
}
}
run(engine_dict['taosd'], test_cases, result_dir)