数据库索引压力测试

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

测试的表结构

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

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

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

matlab演示地月碰撞

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

Signac|成年小鼠大脑 单细胞ATAC分析(2)

引言 在本教程中,我们将探讨由10x Genomics公司提供的成年小鼠大脑细胞的单细胞ATAC-seq数据集。本教程中使用的所有相关文件均可在10x Genomics官方网站上获取。 本教程复现了之前在人类外周血单核细胞(PBMC)的Signac入门教程中执行的命令。…

【linux】进程控制——进程创建,进程退出,进程等待

个人主页:东洛的克莱斯韦克-CSDN博客 祝福语:愿你拥抱自由的风 相关文章 【Linux】进程地址空间-CSDN博客 【linux】详解linux基本指令-CSDN博客 目录 进程控制概述 创建子进程 fork函数 父子进程执行流 原理刨析 常见用法 出错原因 进程退出 概…

7-43 排列问题

排列问题 分数 10 全屏浏览 切换布局 作者 雷丽兰 单位 宜春学院 全排列问题 输出自然数1至n中n个数字的全排列(1≤n≤9),要求所产生的任一数字序列中不允许出现重复的数字。 输入格式: 一个自然数 输出格式: 由1到n中n个数字组成的…

Python魔法之旅专栏(导航)

目录 推荐阅读 1、Python筑基之旅 2、Python函数之旅 3、Python算法之旅 4、博客个人主页 首先,感谢老铁们一直以来对我的支持与厚爱,让我能坚持把Python魔法方法专栏更新完毕! 其次,为了方便大家查阅,我将此专栏…

freertos中的链表1 - 链表的数据结构

1.概述 freertos中链表的实现在 list.c 和 list.h。旨在通过学习freertos中的链表的数据结构,对freertos中的链表实现有一个整体的认识。freertos使用了三个数据结构来描述链表,分别是:List_t, MiniListItem_t,ListIt…

【Linux】进程6——环境变量

1.什么是环境变量 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数 比如:我们在编写C/C代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功&…

Windows 10 找不到Microsoft Edge 浏览器

下载链接 了解 Microsoft Edge 手动下载浏览器 问题说明 一般来说,windows10系统应该是自带浏览器edge的,但有的电脑就是没有找到edge浏览器,可能系统是精简过的,可能是被卸载了。如下,控制面板确实没找到程序。 ​ …

笔记本充电出现了问题。

不知道为什么。电池充电图片一直显示的空。谁能救救我!

C++命名空间的定义、C++命名空间的使用、C++输入输出等的介绍

文章目录 前言一、C命名空间的定义1. C命名空间产生的原因2. 作用域限定符3. C变量的访问顺序 二、C命名空间的使用1. 加命名空间名称及作用域限定符2. 使用using将命名空间中某个成员引入3. 使用using namespace 命名空间名称 引入4. 嵌套命名空间使用 三、 C输入&输出总结…

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

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

C#操作MySQL从入门到精通(14)——汇总数据

前言 我们有时候需要对数据库查询的值进行一些处理,比如求平均值等操作,本文就是详细讲解这些用法,本文测试使用的数据库数据如下: 1、求平均值 求所有student_age 列的平均值 string sql = string.Empty; if (radioButton_AVG.Checked) {sql = “select AVG( student_…

《Vue》系列文章目录

Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以…

真北游记|三江交汇,碧海苍梧,端午去梧州吃龟苓膏

准备 t-14:高铁抢票(A) t-14:订行程(B)酒店(C) T-2:准备水、零食 T-1:物质准备:衣服、纸巾、毛巾、雨伞🌂、拖鞋、口罩😷(D&#xff0…

phpstudy的安装dvwa

phpstudy安装dvwa 1. 下载phpstudy Windows版phpstudy下载 - 小皮面板(phpstudy) (xp.cn) 2. 搭建dvwa靶场 下载地址:https://github.com/ethicalhack3r/DVWA/archive/master.zip 将其放入www文件夹中 3. 修改配置文件 将\DVWA-master\config中config.inc.php…

【深度揭秘】ChatGPT如何成为智能对话的领头羊?万字详解其背后的核心技术!

最近,OpenAI的预训练模型ChatGPT给人工智能领域的研究人员留下了深刻的印象和启发。毫无疑问,它非常强大,与之交流十分有趣,还能编写代码。它在多个方面的表现远超自然语言处理研究者的预期。因此,我们不禁要问&#x…

Nginx之正向代理配置示例和说明

一、NGINX正向代理功能简介 Nginx的正向代理功能允许局域网中的客户端通过代理服务器访问Internet资源。具体来说,Nginx作为一种流行的Web服务器和反向代理服务器,在正向代理方面的应用也相当实用。以下是其正向代理功能的几个关键点: 访问外…

[AI Google] 使用 Gemini 取得更多成就:试用 1.5 Pro 和更多智能功能

总结 Google 正在为超过 35 种语言的 Gemini Advanced 订阅者推出 Gemini 1.5 Pro。此次更新包括 100 万个 token 的上下文窗口、改进的数据分析功能和增强的多模态图像理解。新功能包括用于自然对话的 Gemini Live、先进的规划工具和可定制的 Gems。更新还集成了更多 Google …

【Python项目】——爬虫爬取柯南的剧集数和集名(有错求指点)

项目目的:因为柯宝除了在CSDN写博客这一爱好外,还比较喜欢追番剪辑,尤其是柯南,想到了爬取这个!!参考Github大佬,原项目链接: 原作者Githubhttps://github.com/LorentzForceWorkEnz…