【问题标题】:Create many to many from single table performance issue从单表性能问题创建多对多
【发布时间】:2014-09-20 00:02:03
【问题描述】:

我正在使用一个相当大的数据库(超过 500+ 百万个条目),并且正在尝试优化搜索引擎。

我的主表如下:

项目 (id,混合,值)

mixed 包含与此项目相关的关键字(例如:“Jason Bourne 很酷”)。我想要做的是填充两个新表:

item_terms (id, 术语)

item_term_results (id, item_terms_id, items_id)

来自主表项。我已经编写了一个 MySQL 过程,循环遍历这个主表中的所有结果,遵循这个算法:

  • 拆分项目.mixed
    • 遍历我们得到的值:
      • 在 item_terms 中插入值
      • 在 item_term_results 中插入新结果,将 items.id 放入 item_term_results.items_id 和 item_term_results 中的 last_inserted_id() 中

问题是,该过程需要方式太多时间来处理。有了这么多数据,这个过程需要 150 天才能完成,即使我们在一个非常强大的服务器上,这也太长了。

知道如何做到这一点吗?我们这样做基本上是为了让搜索比简单的like 快很多,因为 item_terms.item 中的值是唯一的。

谢谢

【问题讨论】:

    标签: mysql performance search insert procedure


    【解决方案1】:

    假设您已经完成研究以确定您的不同术语(例如“Jason”、“Bourne”、“cool”的数量在大小上是合理有限的,即使您有一个很大的 items 表。

    大概您还确定 MySQL 的 FULLTEXT 搜索功能不适合您的应用程序。如果您还没有研究过全文搜索,我强烈建议您这样做。这可能是完美的事情。

    您的 item_term_results 表不需要也不应该有单独的 id 列。使主键成为其他两列的组合,并将它们按(item_terms_id, itemid)的顺序放入键中

    我建议您弄清楚如何离线处理批量索引,即与数据库断开连接。这是我的建议:

    1. 转储一个简单但大的文本文件,其中每一行包含id,然后是一个制表符,然后是mixed
    2. 编写执行以下操作的程序。
      1. 阅读表格的每一行。
      2. 将行拆分为单独的项目
      3. 将每个项目插入到内存中的哈希映射中,对其进行去重并为其赋予唯一的item_terms_id,在内存中,而不是在数据库中。
      4. 对于每个项目,在文本文件中写出一行item_id,然后制表符,然后item_terms_id
    3. 处理完输入文件中的所有行后,将每个术语以item_terms_id 的形式写出到另一个文本文件,然后按tab,然后是term 的文本。
    4. 最后,使用 LOAD DATA INFILE 将这两个文件批量导入 MySQL。

    这应该消除进行逐行插入的严重开销。对于半个千兆记录,它将使用大量 RAM 用于内存中的 item_terms 哈希,它可能会运行数小时,但不会运行很多天。

    不过,在您咬紧牙关之前,请再次调查 FULLTEXT。它旨在做您似乎正在做的事情。

    【讨论】:

    • 非常感谢您的快速回复。我没有像使用 TokuDB 一样使用 FULLTEXT,所以我认为这种多对多关系可能会很好用。但是,我不明白为什么关键字的数量仍然很低很重要?由于 item_terms.term 将具有唯一索引,因此搜索它应该仍然非常及时,对吗? (我正在将数据库转换为 InnoDB 并添加全文索引来测试它)
    • 这个想法是对关键字进行重复数据删除,因此搜索会在您的item_terms 表中找到一个条目,然后快速查找您的item_term_results 表中的项目。此外,我的 ETL 策略要求关键字适合 RAM,因此不可能有数十亿个不同的关键字。
    • 经过几天的测试,FULLTEXT确实是解决这个问题的好方法。但是,我无法让它与 InnoDB 一起使用,索引生成总是失败,我不得不切换到 MyISAM 来生成它(我猜条目太多了)。但是,由于我不喜欢 MyISAM,所以我改用 SphinxSearch,它可以使用 TokuDB 并且比 FULLTEXT 索引具有更好的性能。
    猜你喜欢
    • 1970-01-01
    • 2013-07-07
    • 2017-04-30
    • 2013-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多