数据库索引压力测试

news2024/11/23 10:38:27

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

测试的表结构

使用一个菜单的数据库表,包括菜品的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 tqdm


def 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_time
        if 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_time
        if 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 = 100
    spend = 1
    dir = '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_time
        if 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 = 100
    spend = 1
    dir = '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 pd

def 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')

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1807940.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

上位机图像处理和嵌入式模块部署(f407 mcu vs h750)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 在目前工业控制上面,f103和f407是用的最多的两种stm32 mcu。前者频率低一点,功能少一点,一般用在低端的嵌入式设…

N32G45XVL-STB之移植LVGL(lvgl-8.2.0)

目录 概述 1 软硬件介绍 1.1 软件版本信息 1.2 ST7796-LCD 1.3 MCU IO与LCD PIN对应关系 2 认识LVGL 2.1 LVGL官网 2.2 LVGL库文件下载 3 移植LVGL 3.1 准备移植文件 3.2 添加lvgl库文件到项目 3.2.1 src下的文件 3.2.2 examples下的文件 3.2.3 配置文件路径 3.2…

探索国内大模型AIGC产品

​ 人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗…

单片机(STM32)与上位机传输浮点数

目录 单片机(STM32)与上位机传输数据的方法1. 传输整形数据2. 传输浮点数据3. 如何打包与解包 单片机(STM32)与上位机传输数据的方法 在进行单片机程序的开发时,常常需要与其他设备进行通信。一种情况是与其他电路板通信,比如STM32主机与STM32从机通信&…

Windows开始ssh服务+密钥登录+默认启用powershell

文章内所有的命令都在power shell内执行,使用右键单击Windows徽标,选择终端管理员即可打开 Windows下OpenSSH的安装 打开Windows power shell,检查SSH服务的安装状态。会返回SSH客户端和服务器的安装状态,一下是两个都安装成功的…

基于pytoch卷积神经网络水质图像分类实战

具体怎么学习pytorch,看b站刘二大人的视频。 完整代码: import numpy as np import os from PIL import Image import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data…

springboot高校运动会信息管理系统设计与实现-计算机毕业设计源码92968

摘 要 本论文介绍了一个高校运动会信息管理系统的设计和实现过程。首先是高校运动会的需求分析和可行性分析,通过比较运动会的各个工作流程,确定了系统的数据流程和数据库结构,然后介绍了高校运动会信息管理系统开发所使用的软件开发工具&…

脖子以下是人机交互,脖子以上是人机融合智能

“脖子以下是人机交互,脖子以上是人机融合智能”这句话是当前人与人工智能配合技术发展的一种形象描述,一个是生理物理,一个是人脑电脑: 1、人机交互的重要性 脖子以下的人机交互在当前的人工智能系统中扮演着重要的角色。人机交互…

SpringBoot整合RabbitMQ (持续更新中)

RabbitMQ 官网地址:RabbitMQ: One broker to queue them all | RabbitMQ RabbitMQ 与 Erlang 版本兼容关系​ 3.13.0 26.0 26.2.x The 3.13 release series is compatible with Erlang 26. OpenSSL 3 support in Erlang is considered to be mature and ready for…

大数据湖一体化运营管理建设方案(49页PPT)

方案介绍: 本大数据湖一体化运营管理建设方案通过构建统一存储、高效处理、智能分析和安全管控的大数据湖平台,实现了企业数据的集中管理、快速处理和智能分析。该方案具有可扩展性、高性能、智能化、安全性和易用性等特点,能够为企业数字化…

基于51单片机俄罗斯方块小游戏

基于51单片机俄罗斯方块游戏 (仿真+程序) 功能介绍 具体功能: 1.用LCD12864显示游戏界面; 2.用四个按键控制游戏(左、右移、下移、翻转); 3.游戏规则和平时玩的俄罗斯方块一样&a…

Qt窗口与对话框

目录 Qt窗口 1.菜单栏 2.工具栏 3.状态栏 4.滑动窗口 QT对话框 1.基础对话框QDiaog 创建新的ui文件 模态对话框与非模态对话框 2.消息对话框 QMessageBox 3.QColorDialog 4.QFileDialog文件对话框 5.QFontDialog 6.QInputDialog Qt窗口 前言:之前以上…

天才程序员周弈帆 | Stable Diffusion 解读(二):论文精读

本文来源公众号“天才程序员周弈帆”,仅用于学术分享,侵权删,干货满满。 原文链接:Stable Diffusion 解读(二):论文精读 【小小题外话】端午安康! 在上一篇文章天才程序员周弈帆 …

初阶 《函数》 4. 函数的调用

4. 函数的调用 4.1 传值调用 函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参 4.2 传址调用 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是…

【数据分析基础】实验三 文件操作、数组与矩阵运算

一.实验目的 掌握上下文管理语句with的使用方法。掌握文本文件的操作方法。了解os、os.path模块的使用。掌握扩展库Python-docx、openpyxl的安装与操作word、Excel文件内容的方法。熟练掌握numpy数组相关运算和简单应用。熟练使用numpy创建矩阵,熟悉常用…

matlab演示地月碰撞

代码 function EarthMoonCollisionSimulation()% 初始化参数earth_radius 6371; % 地球半径,单位:公里moon_radius 1737; % 月球半径,单位:公里distance 384400; % 地月距离,单位:公里collision_tim…

【JAVASE】java语法(成员变量与局部变量的区别、赋值运算符中的易错点)

一:成员变量与局部变量的区别 区别 成员变量 局部变量 类中位置不同 …

高通Android开关机动画踩坑简单记录

1、下面报错有可能是selinux的原因 Read-only file system 2、接着push 动画 reboot之后抓取logcat出现 ,以下这个报错。看着像是压缩格式有问题。 3、于是重新压缩一下报错没有再出现 ,压缩格式默认是标准,这里必须要改成存储格式哈 4、修改…

python-数字黑洞

[题目描述] 给定一个三位数,要求各位不能相同。例如,352是符合要求的,112是不符合要求的。将这个三位数的三个数字重新排列,得到的最大的数,减去得到的最小的数,形成一个新的三位数。对这个新的三位数可以重…

解决windows11开机xbox自启动

1、同时按键盘“ctrlaltdelete”键,在弹出页面中选择任务管理器; 2、点击启动应用 3、找到软件Xbox App Services,选择“已启用”点击右键,点击禁用;