Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python—如何构建和访问大量数据,而不消耗最大内存或使处理速度减慢到停止状态_Python_Memory_Collections_Persistence_Containers - Fatal编程技术网

Python—如何构建和访问大量数据,而不消耗最大内存或使处理速度减慢到停止状态

Python—如何构建和访问大量数据,而不消耗最大内存或使处理速度减慢到停止状态,python,memory,collections,persistence,containers,Python,Memory,Collections,Persistence,Containers,我正在用Python编写一个脚本,用于在专有ESRI数据库表中控制数据。脚本的目的不是修改无效数据,而是通过csv文件向用户报告无效数据。我正在使用ESRI的ArcPy包使用ArcPy.SearchCursor访问每个记录。SearchCursor是访问ESRI格式的每条记录的唯一方法 当我滚动浏览表的每个记录时,我会进行多个QC检查以验证特定的业务逻辑。其中一项检查是在特定字段中查找重复数据。其中一个字段可能是几何体。为此,我为每个字段创建了一个空容器对象,并在检查每个记录时使用以下逻辑 fo

我正在用Python编写一个脚本,用于在专有ESRI数据库表中控制数据。脚本的目的不是修改无效数据,而是通过csv文件向用户报告无效数据。我正在使用ESRI的ArcPy包使用ArcPy.SearchCursor访问每个记录。SearchCursor是访问ESRI格式的每条记录的唯一方法

当我滚动浏览表的每个记录时,我会进行多个QC检查以验证特定的业务逻辑。其中一项检查是在特定字段中查找重复数据。其中一个字段可能是几何体。为此,我为每个字段创建了一个空容器对象,并在检查每个记录时使用以下逻辑

for field in dupCheckFields:
    if row.getValue(field) in fieldValues[field]: dupValues.add(row.getValue(idField))
    else: fieldValues[field].append(row.getValue(field))
上面的代码是我使用的基本逻辑的一个示例。我遇到的麻烦是,这些表中的每个表可能包含5000条到1000万条记录。我要么是内存不足,要么是演出停滞不前

我尝试了以下容器类型:集合、列表、字典、ZODB+BList和Shelve

对于内存中的类型(集合、列表、字典),这个过程在开始时非常快,但随着它的发展,它会变得慢得多。如果我们使用这些类型,如果表中有许多记录,我将耗尽内存。对于持久性数据类型,我不会耗尽内存,但处理它需要很长时间

我只需要在脚本运行时使用数据,任何持久数据文件都将在完成后删除

问题:在访问数据时,是否有更好的容器类型可以提供大量数据的低内存存储,而不会带来很大的性能成本

系统:Win7 64位,Python 2.6.5 32位,4gb RAM

提前感谢你的帮助

编辑:

SQLite代码示例:

import sqlite3, os, arcpy, timeit

fc = r"path\to\feature\class"

# test feature class was in ESRI ArcSDE format and contained "." characters separating database name, owner, and feature class name
fcName = fc.split(".")[-1]

# convert ESRI data types to SQLite data types
dataTypes = {"String":"text","Guid":"text","Double":"real","SmallInteger":"integer"}

fields = [(field.name,dataTypes[field.type]) for field in arcpy.ListFields(fc) if field.name != arcpy.Describe(fc).OIDFieldName]

# SQL string to create table in SQLite with same schema as feature class
createTableString = """create table %s(%s,primary key(%s))""" % (fcName,",\n".join('%s %s' % field for field in fields),fields[0][0])

# SQL string to insert data into SQLite table
insertString = """insert into %s values(%s)""" % (fcName, ",".join(["?" for i in xrange(len(fields))]))

# location to save SQLite database
loc = r'C:\TEMPORARY_QC_DATA'

def createDB():
    conn = sqlite3.connect(os.path.join(loc,'database.db'))
    cur = conn.cursor()

    cur.execute(createTableString)

    conn.commit()

    rows = arcpy.SearchCursor(fc)

    i = 0
    for row in rows:
        try:
            cur.execute(insertString, [row.getValue(field[0]) for field in fields])
            if i % 10000 == 0:
                print i, "records"
                conn.commit()
            i += 1
        except sqlite3.IntegrityError: pass
    print i, "records"

t1 = timeit.Timer("createDB()","from __main__ import createDB")

print t1.timeit(1)
不幸的是,我无法共享我在该代码中使用的测试数据,但它是一个ESRI ArcSDE地理数据库表,包含约10个字段和约7 mil记录


我试图用
timeit
来确定这个过程花了多长时间,但是经过2个小时的处理,只完成了120000条记录。

如果将哈希存储在(压缩的)文件中,您可以对它们进行流式处理,以比较哈希以查找重复项。流式处理通常具有非常低的内存要求-您可以设置所需的缓冲区,例如,每个哈希记录一行。权衡通常是时间,特别是如果添加压缩,但是如果按照某些标准对文件进行排序,则可以遍历未压缩的流以更快地比较记录。

如果将哈希存储在(压缩的)文件中,则可以通过流来比较哈希以查找重复项。流式处理通常具有非常低的内存要求-您可以设置所需的缓冲区,例如,每个哈希记录一行。权衡通常是时间,特别是如果添加压缩,但如果按照某些标准对文件进行排序,则可以遍历未压缩的流以更快地比较记录。

我想我应该评估在SQLite数据库中存储持久数据(如已知字段VAL和计数)。当然,这是内存使用和性能之间的权衡


如果您使用支持并发访问的持久性机制,那么您可能可以使用以下方法并行处理数据。完成后,可以从数据库生成错误摘要。

我想我应该评估在SQLite数据库中存储持久数据(如已知字段VAL和计数)。当然,这是内存使用和性能之间的权衡


如果您使用支持并发访问的持久性机制,那么您可能可以使用以下方法并行处理数据。一旦完成,就可以从数据库中生成错误摘要。

我不太清楚文件中的哈希和流式处理是什么意思。这是否仅仅意味着将数据保存在预定义组织中的txt文件中,并简单地通过txt来查找特定条目?我已经研究过哈希,这似乎是一个可能的解决方案。但是,一旦识别出重复的散列,如何找到原始数据向用户报告?在散列和标识键(例如,行号或ID)之间保留一个排序的关联数组。当您在两个表之间找到哈希匹配时,您将有记录键来执行所需的查找。您可以使用JSON或其他序列化格式。如果你使用JSON,它是一个文本文件,你可以压缩(如果磁盘空间很充裕的话)并解压缩到一个你可以遍历的流,一个一个散列。我不太清楚你所说的文件中的散列和流是什么意思。这是否仅仅意味着将数据保存在预定义组织中的txt文件中,并简单地通过txt来查找特定条目?我已经研究过哈希,这似乎是一个可能的解决方案。但是,一旦识别出重复的散列,如何找到原始数据向用户报告?在散列和标识键(例如,行号或ID)之间保留一个排序的关联数组。当您在两个表之间找到哈希匹配时,您将有记录键来执行所需的查找。您可以使用JSON或其他序列化格式。如果您使用JSON,它是一个文本文件,您可以对其进行压缩(如果磁盘空间非常宝贵),然后将其解压为一个可以遍历的流,逐个散列。感谢您的回复。我尝试过SQLite,这是我所尝试过的所有性能中最慢的。我尝试了一个包含30000条记录的数据集,在我不得不停止之前花了2个多小时才得到14000条记录。我意识到ESRI SearchCursor是迭代表中记录的一种相当慢的方法,但只是迭代