Mysql 批量创建海量记录的最佳实践
我使用Mysql 批量创建海量记录的最佳实践,mysql,django,performance,orm,Mysql,Django,Performance,Orm,我使用bulk\u create将一百万条记录插入到新表中。需要80秒。Django只使用一个CPU核心(大约25%的CPU,但没有一个核心达到100%),我相信这是有改进潜力的 这是密码 class Stock(models.Model): code = models.CharField(max_length=6, unique=True) name = models.CharField(max_length=8) class Watchers(models.Model):
bulk\u create
将一百万条记录插入到新表中。需要80秒。Django只使用一个CPU核心(大约25%的CPU,但没有一个核心达到100%),我相信这是有改进潜力的
这是密码
class Stock(models.Model):
code = models.CharField(max_length=6, unique=True)
name = models.CharField(max_length=8)
class Watchers(models.Model):
date = models.DateField(db_index=True)
stock = models.ForeignKey(Stock, unique_for_date="date")
num = models.PositiveIntegerField(default=0)
batch = []
for input in inputs:
watcher = Watcher(date=input['date'], stock=get_stock(), num=input['num'])
batch.append(watcher)
Watcher.objects.bulk_create(batch)
我试过几种方法:
批量大小。对我来说,最好的价值大约是4000英镑。这需要80-90秒
ThreadPool()
。速度要慢得多,大约120-140秒日期字段
上的索引。比1慢一点李>
我使用的是MySQL 5.6社区版。存储引擎是MyISAM。这里是配置
[mysqld]
server-id = 1
default-storage-engine = MyISAM
port = 3306
socket = /tmp/mysql.sock
datadir = "{MYSQLDATAPATH}"
skip-external-locking
explicit_defaults_for_timestamp = TRUE
# MyISAM #
key-buffer-size = 32M
max_allowed_packet = 16M
# CACHES AND LIMITS #
tmp-table-size = 32M
max-heap-table-size = 32M
query-cache-type = 0
query-cache-size = 0
max-connections = 500
thread-cache-size = 50
open-files-limit = 65535
table-definition-cache = 1024
table-open-cache = 2048
# LOGGING
log-bin = mysql-bin
binlog_format = mixed
当我导入另一个表(类似的结构,相同的索引,但有9列)时,需要15分钟。时间的增加不是线性的
批量生产有什么问题吗
更新1 虽然我已经接受了答案,但我认为我应该理解其中的奥秘。所以我做了更多的测试,发现Django的模型创建是速度减慢的根本原因。当我有800000条记录时,调用800000次创建模型将非常耗时 ORM框架执行许多我们没有看到的内部工作,例如完整性检查。在我的例子中,大量记录将被导入到一个空的数据库表中,因此不需要进行检查 现在我使用了
cursor.executemany()
,它将800000条4列记录的插入时间从54秒缩短到16秒。并将80万条13列记录的插入时间从13分钟缩短到46秒
根据我的实验,每3000-5000条记录,你就调用
executemany
。我在一次调用中尝试了800k条记录,这非常慢。虽然批量创建在处理HTML表单时可用于保存少量记录,但它并不适合保存数千条记录。正如您已经发现的,它的速度很慢,因为它需要大量内存,并向数据库发送非常大的查询。福图纳利前来救援
LOAD DATA INFILE语句将文本文件中的行读取到
以非常高的速度移动桌子。加载数据填充是对
选择。。。进入外文件
我们可以生成一个类似于使用文档中的以下示例生成的文件
import csv
with open('some.csv', 'wb') as f:
writer = csv.writer(f)
writer.writerows(someiterable)
最后,正如您已经发现的,加载数据的本地选项。。有时可以用于方便
仅当服务器和客户端都已安装时,本地才起作用
配置为允许它
使用此选项时,不需要手动将文件传输到服务器。您可以在客户端生成CSV文件,本地选项将使mysql客户端自动将文件传输到服务器
如果未指定LOCAL,则文件必须位于服务器主机上
并由服务器直接读取
bulk create没有什么问题,但它的设计并不是要一次将数百万条记录加载到数据库中。对于一天结束时的这类任务,没有什么比在中使用加载数据更好的了FILE@e4c5我相信
在本地文件中加载数据
会更快。你想发布一个答案,这样我就可以接受了。非常感谢。抱歉耽搁了。实际上我已经忘记了本地选项,所以回答您的问题就像参加复习课程一样。key\u buffer\u size
应该是可用RAM的10-20%。@RickJames谢谢您的提示。但我的案例似乎不会产生太多mysql数据(大约50MB)。真正的瓶颈是django的ORM。它为查询数据提供了便利,但对于构建海量对象来说,效率不高。最后,我找到了一个很好的解决方案。请参阅问题的“更新1”部分