问题在于:
输出表架构是:
CREATE TABLE [tokens] ([token] TEXT UNIQUE NOT NULL PRIMARY KEY, [count] INTEGER NOT NULL
天真的方法是,对于每个skipgram,我们在现有记录中的表或增量计数器中创建一个新记录:
INSERT OR REPLACE INTO [tokens] VALUES (@token, COALESCE((SELECT count FROM [tokens] WHERE token=@token), 0) + 1)
这种方法的问题是索引会不断更新,当数据库增长到几千兆时,这些更新速度非常慢。我们可以通过创建没有索引的“令牌”表并在处理结束时添加索引来解决这个问题。
问题是必须扫描表的select语句SELECT count FROM [tokens] WHERE token=@token
会显着降低性能。
我到目前为止找到的最好的方法是(我正在使用C#):
创建Dictionary<string,int>
以计算代币。
将令牌添加到此词典中,直到它变得太大而无法放入RAM中。
从字典中插入(不更新)令牌到没有索引的临时表。该表具有以下模式:
CREATE TABLE [temp] ([token] TEXT, [count] INTEGER)
如果有更多令牌,请清除字典并转到步骤2.
将标记从临时表复制到标记表:
INSERT INTO [tokens] SELECT [token], SUM([count]) AS [count] FROM [temp] GROUP BY [token]
此方法仅需24小时处理数据集,但我认为这不是最佳方法,因为步骤5需要24小时中的22小时。
您是否知道可以解决此问题的替代方法?
P.S。我的应用程序是单线程的,我在事务中批量生成上面的插入(每批100000)。
答案 0 :(得分:1)
我建议创建另一个具有相同定义的表,将表填充到某个状态,将结果合并到主表,清除表并开始处理下一组项。
答案 1 :(得分:0)
我建议添加SET TRANSACTION ISOLATION READ UNCOMMITTED
。这意味着计数可能略有下降,特别是在多个尝试同时插入/更新的线程环境中。
答案 2 :(得分:0)
如果你有很多演出......
我建议您不要计算令牌,而是将所有令牌添加到单个表中,并创建一个用于组织令牌的索引。
CREATE TABLE tokens (token TEXT);
CREATE INDEX tokens_token ON tokens (token ASC);
然后一次添加所有令牌......
INSERT INTO tokens VALUES ('Global Warming');
INSERT INTO tokens VALUES ('Global Cooling');
最后执行SELECT ... GROUP BY
SELECT token, COUNT(0) token_count FROM tokens GROUP BY token
答案 3 :(得分:0)
这对我来说是一个使用“计数布隆过滤器”的好地方。
它需要两次传递你的数据,它有点启发式,但它应该很快。 Bloom过滤器允许在恒定时间内进行设置插入和存在测试。计数布隆过滤器计算已找到特定值的数量,而通常的布隆过滤器仅跟踪是否存在。