当前位置: 首页 > news >正文

数据库索引压力测试

本实验测试数据库在有索引和五索引内容上的查询时间随着数据量级增长的变化

测试的表结构

使用一个菜单的数据库表,包括菜品的ID,菜品名和价格

CREATE TABLE `Menu` (`dish_id` int(6) unsigned zerofill NOT NULL AUTO_INCREMENT,`dish_name` varchar(255) NOT NULL,`price` decimal(10,2) NOT NULL,PRIMARY KEY (`dish_id`) USING HASH,UNIQUE KEY `dish_name` (`dish_name`) USING HASH
);

测试程序

使用python程序,插入有两个并发线程(模拟多用户使用),以每秒100条数据插入,然后查询有一个线程,每秒查询一次,同时操作菜单表,查询的是非主键,所有的操作时间都通过日志保存。最终程序会运行到百万级别的数据量,这样才能更清晰的看出有无索引查询的区别

有索引测试程序

import mysql.connector
import threading
import time
import random
import logging
import os
from tqdm import tqdmdef insert_data(user, password, host, database, freq, spend, times,insert_logger
):cnx = mysql.connector.connect(user=user,password=password,host=host,database=database)cursor = cnx.cursor()for _ in tqdm(range(times)):start_time = time.time()for _ in range(freq):dish_name = f"dish_{random.randint(1, 1000000)}"price = random.randint(10, 100)query = "INSERT INTO Menu_2 (dish_name, price) VALUES (%s, %s)"data = (dish_name, price)cursor.execute(query, data)cnx.commit()use_time = time.time() - start_timeif spend - use_time > 0:time.sleep(spend - use_time)insert_logger.info(f"Insert operation took {use_time} seconds")cnx.close()def execute_query(user, password, host, database, freq, spend, times,query_logger
):cnx = mysql.connector.connect(user=user,password=password,host=host,database=database)cursor = cnx.cursor()for _ in tqdm(range(times)):start_time = time.time()dish_id = random.randint(1, 1000000)query = "SELECT * FROM Menu_2 WHERE dish_id = %s"data = (dish_id,)cursor.execute(query, data)cursor.fetchall()use_time = time.time() - start_timeif 1 - use_time > 0:time.sleep(1 - use_time)query_logger.info(f"Query operation took {use_time} seconds")cnx.close()def build_thread(name, log_format, date_format, dir,threads, func, *args,
):logger = logging.getLogger(name)logger.setLevel(logging.INFO)handler = logging.FileHandler(dir + '/' + name + ".log", mode='w')handler.setFormatter(logging.Formatter(log_format, datefmt=date_format))logger.addHandler(handler)args = list(args)args.append(logger)t = threading.Thread(target=func, args=args)threads.append(t)if __name__ == "__main__":user='root'password='123456'host='127.0.0.1'database='db_test'freq = 100spend = 1dir = 'indexlogs'if not os.path.exists(dir):os.makedirs(dir)log_format = "%(asctime)s: %(message)s"date_format = "%Y-%m-%d %H:%M:%S"args = [user, password, host, database, freq, spend, int(1000000/freq)]threads = []build_thread('insert_thread1', log_format, date_format, dir, threads, insert_data, *args)build_thread('insert_thread2', log_format, date_format, dir, threads, insert_data, *args)build_thread('query', log_format, date_format, dir, threads, execute_query, *args)for t in threads:t.start()for t in threads:t.join()

无索引测试程序

主要是修改查询部分的线程函数,有索引测试查询的是主键,无索引测试得使用其他字段,同时main部分也要一些修改

def execute_query(user, password, host, database, freq, spend, times,query_logger
):cnx = mysql.connector.connect(user=user,password=password,host=host,database=database)cursor = cnx.cursor()for _ in tqdm(range(times)):start_time = time.time()dish_name = f"dish_{random.randint(1, 1000000)}"query = "SELECT * FROM Menu_1 WHERE dish_name = %s"data = (dish_name,)cursor.execute(query, data)cursor.fetchall()use_time = time.time() - start_timeif 1 - use_time > 0:time.sleep(1 - use_time)query_logger.info(f"Query operation took {use_time} seconds")cnx.close()if __name__ == "__main__":user='root'password='123456'host='127.0.0.1'database='db_test'freq = 100spend = 1dir = 'noindexlogs'if not os.path.exists(dir):os.makedirs(dir)log_format = "%(asctime)s: %(message)s"date_format = "%Y-%m-%d %H:%M:%S"args = [user, password, host, database, freq, spend, int(1000000/freq)]threads = []build_thread('insert_thread1', log_format, date_format, dir, threads, insert_data, *args)build_thread('insert_thread2', log_format, date_format, dir, threads, insert_data, *args)build_thread('query', log_format, date_format, dir, threads, execute_query, *args)for t in threads:t.start()for t in threads:t.join()

测试结果可视化

因为前面的测试都有日志保存,我们可以提取相关的数据下来做可视化分析,下面是可视化的程序

import os
import matplotlib.pyplot as plt
import pandas as pddef draw_figure(name):dir = name + 'logs'logs = ['insert_thread1.log','insert_thread2.log','query.log']plt.figure(figsize=(10,6))for log in logs:with open(dir + '/' + log, 'r') as file:lines = file.readlines()time = [float(line.split()[-2]) for line in lines]df = pd.DataFrame(time, columns=['Time'])plt.plot(df['Time'], label=log.split('.')[0])plt.title(name + ' pression exp')plt.xlabel('Operation Index')plt.ylabel('Time (seconds)')plt.legend()plt.savefig(dir + '/' + name + '_analyze.png')if __name__ == '__main__':draw_figure('noindex')draw_figure('index')

这样子可以很直观的看到,其实随着数据两级的加大,数据的插入操作时间是不怎么变化的,但是无索引的字段查询时间在呈线性升高,有索引的字段查询时间则很稳定。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • vue实现stompjs+websocket和后端通信(二)
  • 阿奇科技 简单java-swing计算器源码(可用于课设等)
  • 小程序 UI 风格,赏心悦目
  • Linux安装Docker | 使用国内镜像
  • upload-labs-第五关
  • [AI Google] 使用 Gemini 取得更多成就:试用 1.5 Pro 和更多智能功能
  • 1、深度学习-安装
  • DDMA信号处理以及数据处理的流程---DDMA原理介绍
  • MySQL之查询性能优化(八)
  • Android13 Settings 左上角箭头图标点击无效
  • 数 据 类 型
  • 10、架构-从类库到服务之网关路由
  • 基于Java+SpringBoot制作一个软考助手答题小程序
  • 亚马逊 AWS 视频转码功能、AWS Elemental MediaConvert 中创建和管理转码作业
  • 如何获取MySQL中表的大小?(官方校正版)
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • Create React App 使用
  • crontab执行失败的多种原因
  • css属性的继承、初识值、计算值、当前值、应用值
  • DOM的那些事
  • JavaScript 基本功--面试宝典
  • JavaScript 奇技淫巧
  • JavaScript异步流程控制的前世今生
  • Java多态
  • magento2项目上线注意事项
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • SpiderData 2019年2月23日 DApp数据排行榜
  • Spring Cloud Feign的两种使用姿势
  • STAR法则
  • tab.js分享及浏览器兼容性问题汇总
  • 安卓应用性能调试和优化经验分享
  • 通过npm或yarn自动生成vue组件
  • 一道闭包题引发的思考
  • 正则学习笔记
  • ​比特币大跌的 2 个原因
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • $().each和$.each的区别
  • (1)(1.13) SiK无线电高级配置(五)
  • (1)STL算法之遍历容器
  • (2024)docker-compose实战 (9)部署多项目环境(LAMP+react+vue+redis+mysql+nginx)
  • (7) cmake 编译C++程序(二)
  • (java)关于Thread的挂起和恢复
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (十一)手动添加用户和文件的特殊权限
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转载)从 Java 代码到 Java 堆
  • (自用)gtest单元测试
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .NET Core 中的路径问题
  • .NET/C#⾯试题汇总系列:⾯向对象
  • .NET值类型变量“活”在哪?