python实现myql表字段自适应并发插入1000万条数据

进行大数据开发时,我们常常需要造数据去进行性能验证,本文我们将介绍两种方法往mysql中插入1000万条随机数据(可以自己指定数据量),两个方法均可以达到目的,其中方法一为顺序执行,耗时较长;方法二为并发插入,耗时短,同样插入1000万条数据,在8核情况下,方法二耗时约为方法一的1/2。

我们以下面库表结构为例:

# 创建mysql数据库
CREATE DATABASE IF NOT EXISTS test_db;
 
# 创建表
USE test_db;
CREATE TABLE `alex_datagen2mysql` (
  `param_a` int not null,
  `param_b` int not null,
  `param_d` int not null,
  `param_e` int not null,
  `param_f` int not null
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

方法一:顺序(循环)插入

# -*- coding: utf-8 -*-
import datetime
import random
import pymysql

global db


def mysql_connect(database, table, host='localhost', user='root', password='123456', port=3306):
    # 打开数据库连接
    global db
    db = pymysql.connect(host=host,
                         user=user,
                         password=password,
                         database=database,
                         port=port)

    # 使用 cursor() 方法创建一个游标对象 cursor
    cursor = db.cursor()
    print("mysql已连接")
    # 使用 execute()  方法执行 SQL 查询
    sql = "desc %s;" % table
    cursor.execute(sql)
    # 获取表字段名
    fields = [field[0] for field in cursor.fetchall()]
    return fields


def mysql_exit():
    # 关闭数据库连接
    global db
    db.commit()
    db.close()
    print('mysql退出了')


def data2mysql(database, table, nums, host='localhost', user='root', password='123456', port=3306):
    global db
    # 获取表字段名
    fileds = mysql_connect(database, table, host, user, password, port)
    # 获取字段个数
    data_len = len(fileds)
    # 拼接要插入的数据 -- 这里以变量 %s 通配并以()封装
    res = ','.join(['%s' for _ in range(data_len)])
    metadata = '(' + res + ')'
    # 组装SQL插入语句
    sql = "insert into %s values%s" % (table, metadata)
    # 生成nums条数据,每行为data_len个字段
    data = data_gen(nums, data_len)
    cursor = db.cursor()
    for meta in data:
        # 顺序执行SQL插入语句
        cursor.execute(sql % meta)
    mysql_exit()
    return '插入完毕'


# 随机生成数据,col为要生成的数据行数,row为数据字段数
def data_gen(col, row):
    data = list()
    for i in range(col):
        data.append(tuple([str(random.randint(0, 1000)) for _ in range(row)]))
    return data


if __name__ == '__main__':
    # 开始时间
    startTime = datetime.datetime.now()
    # 顺序插入1000万条数据
    print(data2mysql("db_test", "alex_datagen2mysql", 10000000))
    # 结束时间
    endTime = datetime.datetime.now()
    # 执行耗时
    print(endTime - startTime)

方法二:并发插入(推荐)

# -*- coding: utf-8 -*-
import datetime
import random
import pymysql
from multiprocessing import cpu_count, Pool

global db


def mysql_connect(database, table, host='localhost', user='root', password='123456', port=3306):
    # 打开数据库连接
    global db
    db = pymysql.connect(host=host,
                         user=user,
                         password=password,
                         database=database,
                         port=port)

    # 使用 cursor() 方法创建一个游标对象 cursor
    cursor = db.cursor()
    print("mysql已连接")
    # 使用 execute()  方法执行 SQL 查询
    sql = "desc %s;" % table
    cursor.execute(sql)
    # 获取表字段名
    fields = [field[0] for field in cursor.fetchall()]
    return fields


def mysql_exit():
    # 关闭数据库连接
    global db
    db.commit()
    db.close()
    print('mysql退出了')


def data2mysql(database, table, nums, host='localhost', user='root', password='123456', port=3306):
    global db
    # 获取表字段名
    fileds = mysql_connect(database, table, host, user, password, port)
    # 获取字段个数
    data_len = len(fileds)
    # 拼接要插入的数据 -- 这里以变量 %s 通配并以()封装
    res = ','.join(['%s' for _ in range(data_len)])
    metadata = '(' + res + ')'
    # 组装SQL插入语句
    sql = "insert into %s values%s" % (table, metadata)
    # 生成nums条数据,每行为data_len个字段
    data = data_gen(nums, data_len)
    cursor = db.cursor()
    # 顺序执行SQL插入语句,此处可优化为拼接逻辑
    for meta in data:
        # 顺序执行SQL插入语句
        cursor.execute(sql % meta)
    mysql_exit()
    return '插入完毕'


# 随机生成数据,col为要生成的数据行数,row为数据字段数
def data_gen(col, row):
    data = list()
    for i in range(col):
        data.append(tuple([str(random.randint(0, 1000)) for _ in range(row)]))
    return data


if __name__ == '__main__':
    # 开始时间
    startTime = datetime.datetime.now()
    # 并发插入1000万条数据
    p = Pool(cpu_count())
    # 此处可优化为多个进程在数据库建立一次连接条件下执行,当前开了8个连接数,会产生一定耗时
    for _ in range(cpu_count()):
        p.apply_async(data2mysql, ("db_test", "alex_datagen2mysql", 1250000))
    # 关闭进程池
    p.close()
    p.join()
    # 结束时间
    endTime = datetime.datetime.now()
    # 执行耗时
    print(endTime - startTime)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值