Python算法对大块数据进行排序

时间:2013-08-28 15:34:59

标签: python database sqlite sorting ldif

我一直在网上寻找一种方法来对我拥有的数据进行排序(LDIF文件),但我还没有找到我所追求的内容。已经有程序可以完成这种排序,但它们会因极大的数据集而失败。好吧,对我来说,非常大的是大约2 GB的这些块,这在使用ldifsort.pl脚本时耗尽内存,即使我有6 GB RAM可用和几个GB的交换。所以我希望编写一个程序,将数据块存储到硬盘驱动器中,对内存中的键进行排序,然后按排序顺序重新组装块。我想使用python3,因为我正在努力学习这门语言。因此,如果有人对基本策略或使用python3的具体方法提出建议,我真的很感激帮助。

我有包含LDAP数据的大型文本文件,基本上是以(简化为)形式:

dn: Subscriber=UniqueName1@domain.com;RestOfTree=node1
groups: 1
permissions: 1
IsActive: FALSE
Barring: TRUE

dn: ProfileID=UniqueName1@domain.com;Subscriber=UniqueName1;RestOfTree=node1
groups: 1
permissions: 1
ServiceProfile: Lemur

dn: Subscriber=UniqueName2@domain.com;RestOfTree=node1
groups: 1
permissions: 1
IsActive: FALSE
Barring: TRUE

dn: ProfileID=UniqueName2@domain.com;Subscriber=UniqueName2;RestOfTree=node1
groups: 1
permissions: 1
ServiceProfile: Lemur

每个订户还有三个与之关联的块(我的示例代码仅显示与订户关联的另一个块),并且我希望在排序完成后将所有四个块保持在一起。

因此,如果我按此顺序读取dn(为简洁起见隐藏了与dn相关的数据):

dn: Subscriber=UniqueName2@domain.com;RestOfTree=node
dn: ProfileID=UniqueName2@domain.com;Subscriber=UniqueName2;RestOfTree=node
dn: Subscriber=UniqueName4@domain.com;RestOfTree=node
dn: ProfileID=UniqueName4@domain.com;Subscriber=UniqueName4;RestOfTree=node
dn: Subscriber=UniqueName1@domain.com;RestOfTree=node
dn: Subscriber=UniqueName3@domain.com;RestOfTree=node
dn: ProfileID=UniqueName3@domain.com;Subscriber=UniqueName3;RestOfTree=node
dn: ProfileID=UniqueName1@domain.com;Subscriber=UniqueName1;RestOfTree=node

我希望输出为:

dn: Subscriber=UniqueName1@domain.com;RestOfTree=node
dn: ProfileID=UniqueName1@domain.com;Subscriber=UniqueName1;RestOfTree=node
dn: Subscriber=UniqueName2@domain.com;RestOfTree=node
dn: ProfileID=UniqueName2@domain.com;Subscriber=UniqueName2;RestOfTree=node
dn: Subscriber=UniqueName3@domain.com;RestOfTree=node
dn: ProfileID=UniqueName3@domain.com;Subscriber=UniqueName3;RestOfTree=node
dn: Subscriber=UniqueName4@domain.com;RestOfTree=node
dn: ProfileID=UniqueName4@domain.com;Subscriber=UniqueName4;RestOfTree=node

我曾经想到的是使用sqlite3来存储数据,因为python读取它,然后在python中对键进行排序,然后使用查询从sqlite中再次提取数据并将数据写入文件。但我担心在sqlite中搜索密钥的时间过长。然后我想我可以在插入数据时对sqlite中的数据进行排序,但似乎sqlite不支持这个,我不知道是否有另一个数据库系统。

感谢任何帮助或指示。

感谢Zach建议只使用GNU排序而不是数据库系统。这是我在他的帮助下开发的解决方案。

awk -f ldifformatter.awk LDAP-data-files * .ldif | sort -t \ | -k1 | sed'1d; s / | / \ n / g'> sorted.txt

其中ldifformatter.awk用“|”交换所有换行符除了用于排序的顶级dn。

谢谢, 生锈的

3 个答案:

答案 0 :(得分:2)

您不应该在内存中对数据进行排序。您可以使用merge sort

Guido van Rossum撰写了一篇关于同一问题的文章 - Sorting a million 32-bit integers in 2MB of RAM using Python。本文中有代码示例。

答案 1 :(得分:1)

命令行sort实用程序可以对非常大的文本文件进行排序,而无需将它们完全读入内存(至少GNU版本可以)。但是,要使用它,您必须重新格式化数据,以便每条记录(应该保存在一起的所有内容)出现在一行上。如果记录看起来像这样:

dn: Subscriber=UniqueName1@domain.com;RestOfTree=node1|groups: 1|permissions: 1|IsActive: FALSE|Barring: TRUE||dn: ProfileID=UniqueName1@domain.com;Subscriber=UniqueName1;RestOfTree=node1|groups: 1|permissions: 1|ServiceProfile: Lemur

然后sort -t \| -k1将完成这项工作。

您可以使用Python编写程序,以适当的格式将数据流式传输到临时文件中,使用subprocess.check_call调用sort,然后恢复原始格式。使用tmpfile.NamedTemporaryFile创建临时文件。

答案 2 :(得分:0)

我想知道SQLite是否真的不能胜任这项任务。但无论如何,您可以使用外部排序算法,例如Mergesort,以降低内存使用率。

http://en.wikipedia.org/wiki/External_sorting