设置用于聚类分析的 SQLite 数据库

Setting up SQLite database for cluster analysis

我对数据库完全陌生。我想获得一些关于如何设置和使用 SQLite 数据库进行聚类分析和主题建模任务的建议。

我有一个 2 GB 的文件,其中每一行都是一个 json 对象。这是来自文件的 json 对象示例:

{"body": "Heath Ledger's Joker...", "subreddit_id": "t5_2qh3s", "name": "t1_clpmhgo", "author": "l3thaln3ss", "created_utc": "1414799999", "subreddit": "movies", "parent_id": "t3_2kwdi3", "score": 1, "link_id": "t3_2kwdi3", "sub_type": "links - high"}

我已经像这样创建了一个 SQLite 数据库:

import json
import sqlite3
import sys

def main(argv):
    if len(argv) != 2:
        sys.exit("Provide a database name.")

    dbName = argv[1]
    db = sqlite3.connect(dbName)

    db.execute('''CREATE TABLE IF NOT EXISTS Comments
              (name text primary key,
               author text,
               body text,
               score integer,
               parent_id text,
               link_id text,
               subreddit text,
               subreddit_id text,
               sub_type text,
               created_utc text,
               foreign key (parent_id) references Comment(name));''')

    db.commit()
    db.close()

if __name__ == "__main__":
    main(sys.argv)

这是数据库的良好初始设置吗?

我正在像这样填充数据库:

import json
import sqlite3
import sys

def main(argv):
    if len(argv) != 2:
        sys.exit("Provide a comment file (of json objects) name.")

    fname = argv[1]

    db = sqlite3.connect("commentDB")
    columns = ['name', 'author', 'body', 'score', 'parent_id', 'link_id', 'subreddit', 'subreddit_id', 'sub_type', 'created_utc']

    query = "insert or ignore into Comments values (?,?,?,?,?,?,?,?,?,?)"

    c = db.cursor()

    with open(fname, 'r') as infile:
        for comment in infile:
            decodedComment = json.loads(comment)
            keys = ()
            for col in columns:
                keys += (decodedComment[col],)
            print str(keys)
            print
            c.execute(query, keys)

    c.close()
    db.commit()
    db.close()


if __name__ == "__main__":
    main(sys.argv)

最终,我将根据评论中共享的常用词、用户评论的位置以及通过分析在 subreddit 评论中找到的词获得的主题模型差异来对 subreddit 进行聚类。请注意,我有更多 2 GB 的文件要处理,因此理想情况下,解决方案应该具有相对可扩展性。任何有关如何设置(尤其是通过改进我所写的内容)数据库来完成此类工作的一般性建议将不胜感激。

谢谢!

编辑:删除了有关插入性能的问题。

一些小的改进表明了自己——例如,CommentsCREATE TABLE 有一个 references Comment(name),我很确定 Comment 是一个拼写错误并且你的意思是Comments(所以你发布的代码不起作用)。

速度方面,将特别命名的 keys 构建为 tuple 有点浪费——list 会好得多,即替换

        keys = ()
        for col in columns:
            keys += (decodedComment[col],)

        keys = [decodedComment[col] for col in columns]

为了稍微好一点的性能(可能没有明确记录,但是游标的 execute 方法采用第二个参数,它是一个列表,就像它采用元组一样愉快)。

但总的来说,您的开端不错——在摄取单个 2GB 输入文件后应该没问题。 但是,sqlite,虽然在很多方面都很棒,但并不能很好地扩展到那个大小的倍数——你需要一个 "real" 数据库。我会推荐 PostgreSQL,但可能 MySQL(及其变体,例如 MariaDB)和商业(非开源)产品也不错。

如果 "many more"(2GB 文件)是指数百或数千,甚至 "serious" 专业数据库可能在某个时候开始在接缝处吱吱作响,具体取决于您计划的处理方式向他们投掷; "every word in the comment" 的提及(暗示我想 body 字段需要被处理——词干 &c——进入一个单词集合)在承诺非常繁重的处理即将到来时有点令人担忧。

一旦这成为一个问题,"NoSQL" 产品或 严重 旨在扩大规模的东西,例如 BigQuery,可能值得您花时间。然而,对于小规模的实验,你当然可以从 sqlite 开始,用它来开发你想要的 "clustering" 的算法;然后扩展到 PostgreSQL 或其他任何东西,以检查这些扩展在中等规模上的工作方式;只有在那个时候,如果需要,才需要额外的工作来考虑非关系解决方案,虽然非常强大,但往往需要承诺某些访问模式(关系数据库,您最可能需要的是添加索引,可能更适合更多实验阶段的游戏!)。

传统的 SQL 和 NoSQL 数据库对于此类分析不是特别有用。缺乏允许精细获得的相似性的能力,或根据需要通过聚类算法加速查询的能力。

在大多数实际使用中,您最终会得到这样的工作流程:

  1. 将数据库中的数据加载到分析应用程序中(通常通过将其转储为某种 CSV 格式)
  2. 执行分析
  3. 将结果写回数据库

这不是很漂亮或效率很高,肯定会让您失望。但考虑到即使在商业报价中也缺乏分析灵活性,这就是我们所拥有的。甚至某些商业报价中可用的分析功能(其中一些功能已经足够)也经常以这种方式工作。

在您的特定用例中,可以使用 Lucene 作为后备数据库。如果你有一个聚类算法实现可以通过Lucene查询加速,那就是。