【问题标题】:Speed up database inserts from ORM从 ORM 加速数据库插入
【发布时间】:2010-11-26 21:52:45
【问题描述】:

我有一个 Django 视图,它在循环中创建 500-5000 个新数据库 INSERTS。问题是,它真的很慢!我在 Postgres 8.3 上每分钟插入大约 100 次。我们曾经在较小的硬件(较小的 EC2 实例)上使用 MySQL,并且从未遇到过这些类型的速度问题。

详情: Ubuntu 服务器 9.04 上的 Postgres 8.3。 服务器是一个“大型”Amazon EC2,数据库位于 EBS (ext3) - 11GB/20GB。

这是我的一些 postgresql.conf -- 如果您需要更多信息,请告诉我

shared_buffers = 4000MB
effective_cache_size = 7128MB

我的蟒蛇:

for k in kw:
        k = k.lower()
        p = ProfileKeyword(profile=self)
        logging.debug(k)
        p.keyword, created = Keyword.objects.get_or_create(keyword=k, defaults={'keyword':k,})
        if not created and ProfileKeyword.objects.filter(profile=self, keyword=p.keyword).count():
            #checking created is just a small optimization to save some database hits on new keywords
            pass #duplicate entry
        else:
            p.save()

顶部的一些输出:

top - 16:56:22 up 21 days, 20:55,  4 users,  load average: 0.99, 1.01, 0.94
Tasks:  68 total,   1 running,  67 sleeping,   0 stopped,   0 zombie
Cpu(s):  5.8%us,  0.2%sy,  0.0%ni, 90.5%id,  0.7%wa,  0.0%hi,  0.0%si,  2.8%st
Mem:  15736360k total, 12527788k used,  3208572k free,   332188k buffers
Swap:        0k total,        0k used,        0k free, 11322048k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                            
14767 postgres  25   0 4164m 117m 114m S   22  0.8   2:52.00 postgres                                                                                                                                            
    1 root      20   0  4024  700  592 S    0  0.0   0:01.09 init                                                                                                                                                
    2 root      RT   0     0    0    0 S    0  0.0   0:11.76 migration/0                                                                                                                                         
    3 root      34  19     0    0    0 S    0  0.0   0:00.00 ksoftirqd/0                                                                                                                                         
    4 root      RT   0     0    0    0 S    0  0.0   0:00.00 watchdog/0                                                                                                                                          
    5 root      10  -5     0    0    0 S    0  0.0   0:00.08 events/0                                                                                                                                            
    6 root      11  -5     0    0    0 S    0  0.0   0:00.00 khelper                                                                                                                                             
    7 root      10  -5     0    0    0 S    0  0.0   0:00.00 kthread                                                                                                                                             
    9 root      10  -5     0    0    0 S    0  0.0   0:00.00 xenwatch                                                                                                                                            
   10 root      10  -5     0    0    0 S    0  0.0   0:00.00 xenbus                                                                                                                                              
   18 root      RT  -5     0    0    0 S    0  0.0   0:11.84 migration/1                                                                                                                                         
   19 root      34  19     0    0    0 S    0  0.0   0:00.01 ksoftirqd/1 

如果有任何其他细节有帮助,请告诉我。

【问题讨论】:

    标签: django postgresql django-models amazon-ec2


    【解决方案1】:

    像这样缓慢的批量操作的一个常见原因是每个插入都发生在自己的事务中。如果您可以让所有这些都发生在一个事务中,它可能会更快。

    【讨论】:

    【解决方案2】:

    首先,ORM 操作总是比纯 SQL 慢。我曾经用 ORM 代码写了一个大型数据库的更新并设置它运行,但几个小时后它只完成了一小部分就退出了。用 SQL 重写后,整个过程不到一分钟就跑完了。

    其次,请记住,您的代码对数据集中的每一行最多执行四个单独的数据库操作 - get_or_create 中的get,也可能还有过滤器上的createcount,最后是save。数据库访问量很大。

    请记住,最多 5000 个对象并不大,您应该能够在开始时将整个数据集读入内存。然后,您可以使用单个 filter 一次性获取所有现有的 Keyword 对象,从而在 Keyword get_or_create 中节省大量查询,并且还避免了首先实例化重复 ProfileKeywords 的需要。

    【讨论】:

    • +1 指出如果可以的话,一次读取所有内容会更有效,并且每次都不要进行额外的过滤。
    • @Daniel Roseman:你能扩展一下“然后你可以做一个过滤器来获取所有现有的关键字对象......”吗?实际上,我的数据库中已经有几百万个关键字对象,所以我不想将它们全部读入内存。我一次插入 5000 个新对象....
    • 我最终使用 Keyword.objects.filter(keyword__contains=...) 将相关的关键字对象读入内存。脚本现在运行不到 10 秒!!我还添加了事务保存点....
    猜你喜欢
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    • 2014-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多