gpt4 book ai didi

python - 最小化加载多对多关系的性能问题

转载 作者:太空狗 更新时间:2023-10-30 00:07:17 25 4
gpt4 key购买 nike

我一直在标记一个非常大的语料库。每个 Unigram 可以多次出现在多个评论中。我将 Comment.ids 存储在一个列表中,该列表每 250K 个新计算的 unigrams 附加到数据库中的 Unigrams。我想知道的是,是否有一种方法可以扩展评论 ID 列表——或类似的数据结构——而无需查询和加载现有的与 Unigram 相关的评论列表(它可以数以千计)。还是没有解决慢 IO 的办法?

这是我的模型代码:

comments = db.Table('ngrams',
db.Column('unigram_id', db.String, db.ForeignKey('comment.id')),
db.Column('comment_id', db.String, db.ForeignKey('unigram.id')))

class Unigram(db.Model):
id = db.Column(db.String, primary_key=True, unique=True)
times_occurred = db.Column(db.Integer)
occurs_in = db.relationship('Comment', secondary=comments,
backref=db.backref('unigrams', lazy='dynamic'))

class Comment(db.Model):
id = db.Column(db.String, primary_key=True, unique=True)
creation_time = db.Column(db.DateTime)

以及添加新计数和 Comment.ids 的代码:

current = Unigram.query.filter(Unigram.id == ngram).first()
if current:
current.times_occurred += counts[ngram]['count']
current.occurs_in.extend(counts[ngram]['occurences'])
else:
current = Unigram(ngram, counts[ngram]['count'],
counts[ngram]['occurences'])
db.session.add(current)

最佳答案

您具体问题的答案(我认为): http://docs.sqlalchemy.org/en/rel_0_7/orm/collections.html#dynamic-relationship-loaders

The default behavior of relationship() is to fully load the collection of items in ... A key feature to enable management of a large collection is the so-called “dynamic” relationship. This is an optional form of relationship() which returns a Query object in place of a collection when accessed.

看起来 SQLAlchemy 确实支持不必读取集合来修改它。所以 lazy='dynamic' 是正确的。问题可能是你只在 backref 上有它。试试这两种变体:

occurs_in = db.relationship('Comment', secondary=comments, 
lazy='dynamic', backref=db.backref('unigrams'))

occurs_in = db.relationship('Comment', secondary=comments,
lazy='dynamic', backref=db.backref('unigrams', lazy='dynamic'))

另外,您也可以尝试 lazy='noload'。由于您只是在索引期间写入表,因此这将同样有效。

现在,对于更广泛的问题:为什么要这样做?这样做会令人沮丧,即使在您解决了这个小问题之后。一些想法...

使用正确的工具来完成工作:Sphinx、ElasticSearch、Lucene、Solr、Xapian,其中任何一个都可以非常彻底地处理文本索引问题,并且比不使用专门工具更好地处理它。 Sphinx 的执行速度特别快,索引速度为每秒数百兆字节,查询包含一个单词的文档数量通常需要一两毫秒(无论语料库大小如何)。

如果你正在做一个一次性的脚本或测试代码,而不是建立一个生产系统,并且出于某种原因不想使用正确的工具,那么就在内存中做这一切,不要使用SQL。在 python 中使用普通字典,并在两次运行之间将它们保存为 ramdisk 上的 pickle 文件。买更多的内存,它比你的时间便宜。这是在文本语料库上测试统计思想的不错方法。

如果出于某种原因(为什么?)您真的必须在 SQL 数据库中放置一个文本索引,那么请不要使用像 SQLAlchemy 这样的对象关系映射器,这样可以省去很多麻烦。最好的方法是,以合适的格式(如文本文件)准备数据转储,然后一次性将其加载到数据库中(在 MySQL 中使用类似 LOAD DATA INFILE 的方法,或者数据库中的等效项)。这比 快几个数量级。它可以很容易地达到为每个 unigram 运行单独的 INSERT 查询的速度的 1000 倍。如果您以正确的方式组织表格,您以后仍然可以通过 SQLAlchemy 访问数据,但是当您为文本编制索引时,您希望绕过它。

关于python - 最小化加载多对多关系的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21371518/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com