【问题标题】:How to efficiently use MySQLDB SScursor?如何高效使用 MySQLDB SScursor?
【发布时间】:2010-12-20 22:59:33
【问题描述】:

我必须处理一个大型结果集(可能有数十万行,有时甚至更多)。
不幸的是,它们需要一次全部检索(在启动时)。

我正在尝试通过使用尽可能少的内存来做到这一点。
通过查看 SO,我发现使用 SSCursor 可能是我正在寻找的,但我仍然不知道如何准确地使用它们。

从基本游标或 SScursor 执行 fetchall() 是否相同(就内存使用而言)?

我可以从 sscursor 中逐行(或逐行)“流式传输”吗?如果可以, 最有效的方法是什么?

【问题讨论】:

    标签: python mysql optimization database-cursor


    【解决方案1】:

    在获取大结果集时一定要使用 SSCursor。当我遇到类似的问题时,这对我产生了巨大的影响。你可以这样使用它:

    import MySQLdb
    import MySQLdb.cursors
    
    connection = MySQLdb.connect(
            host=host, port=port, user=username, passwd=password, db=database, 
            cursorclass=MySQLdb.cursors.SSCursor) # put the cursorclass here
    cursor = connection.cursor()
    

    现在您可以使用cursor.execute() 执行查询并将光标用作迭代器。

    编辑:删除不必要的本地迭代器,感谢 Denis!

    【讨论】:

    • Cursor 对象是可迭代的,因此无需在其上编写生成器。否则你可以使用iter(cursor.fetchone, None)
    【解决方案2】:

    我同意 Otto Allmendinger 的回答,但要明确 Denis Otkidach 的评论,以下是如何在不使用 Otto 的 fetch() 函数的情况下迭代结果:

    import MySQLdb.cursors
    connection=MySQLdb.connect(
        host="thehost",user="theuser",
        passwd="thepassword",db="thedb",
        cursorclass = MySQLdb.cursors.SSCursor)
    cursor=connection.cursor()
    cursor.execute(query)
    for row in cursor:
        print(row)
    

    【讨论】:

    • 这会一一获取行吗?如果不是这样一次获取多少行。我有一个包含超过 3700 万条记录的数据库。我需要一一阅读记录并将它们放入文件中(还有一些额外的东西,所以不能是简单的转储)。这可以以某种方式并行完成。例如,我获取 10000 行写入它们,当我写入它们时,一些行正在被获取等等..
    • @Sohaib:这一次获取一行。如果您的问题是 CPU 密集型的,那么您可以使用 multiprocessing (Python2/3) 或 concurrent.futures (在 Python3 中) 来设置多个 DB 读取器,但您应该只对文件使用一个写入器,否则记录将得到乱码。 If your problem is IO-bound -- 如果写入文件是瓶颈 -- 那么设置多个阅读器不会加快工作速度。
    • 不会cursor.arraysize 设置每个请求要获取的记录数吗?不确定它是否仅适用于fetchmany 而不适用于fetchone,但如果MySQLdb 支持,它应该很方便。
    • 如何关闭此连接? connection.close()?
    【解决方案3】:

    或者,您可以在连接对象之外使用SSCursor(当您已经定义连接并且不希望所有连接都使用SSCursor 作为游标类时,这一点非常重要)。

    import MySQLdb
    from MySQLdb.cursors import SSCursor # or you can use SSDictCursor
    
    connection = MySQLdb.connect(
            host=host, port=port, user=username, passwd=password, db=database)
    cursor = SSCursor(connection)
    cursor.execute(query)
    for row in cursor:
        print(row)   
    

    【讨论】:

      猜你喜欢
      • 2014-11-04
      • 2016-03-12
      • 2013-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-15
      • 2019-05-18
      • 2011-09-21
      相关资源
      最近更新 更多