【问题标题】:database for analytics用于分析的数据库
【发布时间】:2009-04-03 05:13:04
【问题描述】:

我正在建立一个大型数据库,它将根据传入的数据生成统计报告。
系统大部分操作如下:

  1. 每天早上将上传大约 400k-500k 行 - 大约 30 列,主要是 varchar(5-30) 和 datetime。它在平面文件形式时约为 60MB,但在添加合适的索引后在数据库中急剧增长。
  2. 将从当天的数据生成各种统计数据。
  3. 将生成并存储来自这些统计数据的报告。
  4. 当前数据集将被复制到分区历史表中。
  5. 一整天,最终用户都可以查询当前数据集(已复制,未移动),以获取不太可能包含常量但字段之间关系的信息。
  6. 用户可以从历史记录表中请求专门的搜索,但查询将由 DBA 精心设计。
  7. 在第二天上传之前,当前数据表被截断。

这基本上是我们现有系统的第 2 版。

现在,我们正在使用 MySQL 5.0 MyISAM 表(Innodb 仅在空间使用方面就被扼杀了)并且在 #6 和 #4 上遭受了很大的损失。 #4 目前不是分区表,因为 5.0 不支持它。为了避免将记录插入历史记录所花费的大量时间(数小时和数小时),我们每天都将写入一个未索引的 history_queue 表,然后在我们最慢的时间的周末,将队列写入历史表。问题是一周内生成的任何历史查询都可能晚几天。我们无法减少历史表上的索引,否则它的查询将变得不可用。

我们肯定会在下一个版本中至少迁移到 MySQL 5.1(如果我们继续使用 MySQL),但强烈考虑使用 PostgreSQL。我知道辩论已经进行到死,但我想知道是否有人对这种情况有任何建议。大多数研究都围绕网站使用展开。索引确实是我们使用 MySQL 的主要优势,似乎 PostgreSQL 可以通过部分索引和基于函数的索引来帮助我们。

我已经阅读了几十篇关于两者之间差异的文章,但大多数都是旧的。 PostgreSQL 长期以来一直被贴上“更高级但更慢”的标签——将 MySQL 5.1 与 PostgreSQL 8.3 进行比较还是普遍情况还是现在更平衡?

商业数据库(Oracle 和 MS SQL)根本不是一种选择——尽管我希望 Oracle 是。

关于 MyISAM 与 Innodb 的注意事项: 我们正在运行 Innodb,对我们来说,我们发现它要慢得多,比如慢 3-4 倍。但是,我们对 MySQL 也较新,坦率地说,我不确定我们是否为 Innodb 适当调整了 db。

我们在正常运行时间非常长的环境中运行 - 备用电池、故障转移网络连接、备用发电机、完全冗余系统等。因此,对 MyISAM 的完整性问题进行了权衡并认为是可以接受的。

关于 5.1: 我听说过 5.1 的稳定性问题。一般来说,我认为任何最近(过去 12 个月内)的软件都不是坚如磐石的稳定。考虑到重新设计项目的机会,5.1 中的更新功能集实在是太多了。

关于 PostgreSQL 陷阱: 没有任何 where 子句的 COUNT(*) 对我们来说是非常罕见的情况。我不认为这是一个问题。 COPY FROM 不如 LOAD DATA INFILE 灵活,但中间加载表可以解决这个问题。 我最担心的是缺少 INSERT IGNORE。我们经常在构建一些处理表时使用它,这样我们就可以避免将多条记录放入两次,然后不得不在最后做一个巨大的 GROUP BY 来删除一些重复。我认为它的使用频率很低,以至于缺乏它是可以容忍的。

【问题讨论】:

  • 我相信你已经调整了 my.cnf ?
  • 是的,我们已经尽我们所能调整了 my.cnf。我们已经解释了每个静态查询并进行了相应的调整。
  • "我希望 Oracle 是 [一个选项]" 那么您可能需要 Postgres;它很容易成为大型开源数据库中最像 Oracle 的,并且在最近的 SPEC 性能测试中已经接近 Oracle。
  • “在最近的 SPEC 性能测试中接近 Oracle” - 链接?
  • it.toolbox.com/blogs/database-soup/… 执行摘要:Postgres 在硬件上达到了 Oracle 10 的 85% 性能,并且便宜了 10%。而且 Postgres 的成本不超过 110,000 美元。

标签: mysql postgresql indexing infobright


【解决方案1】:

我的工作尝试了一个从 ERP 设置迁移历史数据的试点项目。数据量偏小,只有 60Gbyte,覆盖超过 2100 万行,最大的表有 1600 万行。还有大约 1500 万行等待进入管道,但由于其他优先事项,该试点已被搁置。该计划是使用 PostgreSQL 的“作业”工具来安排查询,这些查询将每天重新生成适合用于分析的数据。

在包含 1600 万条记录的大型表上运行简单聚合,我注意到的第一件事是它对可用 RAM 量的敏感程度。一次增加的 RAM 允许在不使用顺序表扫描的情况下进行一年的聚合。

如果您决定使用 PostgreSQL,我强烈建议您重新调整配置文件,因为它往往带有最保守的设置(这样它就可以在 RAM 很少的系统上运行)。调整需要一点时间,可能需要几个小时,但一旦你将其调整到可以接受响应的程度,只需设置它并忘记它。

一旦您完成了服务器端调优(这全都与内存有关,令人惊讶!)您将把注意力转向您的索引。索引和查询计划也需要一些努力,但一旦设置,您会发现它是有效的。部分索引是一个很好的功能,可以隔离那些包含“边缘情况”数据的记录,如果您正在寻找类似数据的海洋中的异常,我强烈推荐这个功能。

最后,使用表空间功能将数据重定位到快速驱动器阵列上。

【讨论】:

  • 我真的认为部分索引可能对我们的一些历史查询有很大帮助——这是我们将其视为 PostgreSQL 的最大原因之一。我们已经开始尝试调整,但我们没有完全设置数据库,所以我们已经提交调整,直到我们得到一些完整的数据集。
【解决方案2】:

在我的实践经验中,我不得不说,postgresql 的性能从 7.x/8.0 到 8.1 有相当大的提升(对于我们的用例,在某些情况下快 2 到 3 倍),从 8.1 到 8.2 的改进较小但是仍然很明显。我不知道 8.2 和 8.3 之间的改进,但我希望也有一些性能改进,我到目前为止还没有测试过。

关于索引,我建议删除那些,然后在用您的数据填充数据库后重新创建它们,这样会快得多。

进一步改进你的 postgresql 设置的废话,从中获得很多好处。默认设置现在至少是明智的,在 8.2 倍之前,pg 已针对在 pda 上运行进行了优化。

在某些情况下,特别是如果您有复杂的查询,它可以帮助您停用设置中的嵌套循环,这会迫使 pg 对您的查询使用性能更好的方法。

啊,是的,我说你应该去 postgresql 吗?

(另一种选择是 firebird,它不太灵活,但根据我的经验,它在某些情况下的性能比 mysql 和 postgresql 好得多)

【讨论】:

    【解决方案3】:

    根据我的经验,对于非常简单的查询,Inodb 的速度要快一些,对于更复杂的查询,则使用 pg。 Myisam 在检索方面可能比 Innodb 更快,但在索引/索引修复方面可能更慢。

    这些主要是 varchar 字段,您是否使用 char(n) 索引对它们进行索引?

    你能把它们中的一些标准化吗?重写会花费您,但可能会节省后续查询的时间,因为您的行大小会减小,从而一次将更多行放入内存中。

    编辑中:

    好的,所以你有两个问题,查询时间和更新历史,是吗?

    至于第二个:根据我的经验,mysql myism 不擅长重新索引。在每天大小的表(0.5 到 1M 记录,具有相当宽的(非规范化平面输入)记录)上,我发现重写表比插入并等待重新索引和伴随的磁盘抖动更快。

    所以这可能或可能没有帮助:

    create new_table select * from old_table ;
    

    复制表格但不复制索引。

    然后像往常一样插入新记录。然后在新表上创建索引,稍等片刻。删除旧表,将新表重命名为旧表。

    编辑:回应第四条评论:我不知道 MyIsam 总是那么糟糕。我知道在我的特殊情况下,我对复制表然后添加索引的速度有多快感到震惊。碰巧的是,我正在做与您所做的类似的事情,将大型非规范化平面文件复制到数据库中,然后重新规范化数据。但这是一个轶事,而不是数据。 ;)

    (我还认为我发现整体 InnoDb 更快,因为我执行的插入操作和查询操作一样多。数据库使用的一个非常特殊的情况。)

    请注意,使用 select a.*, b.value as foo join ... 进行复制也比更新 a.foo = b.value ... join 更快,因为更新是针对索引的列。

    【讨论】:

    • 它们是索引 char(n),是的。它在有意义的地方进行了归一化,但是大多数在本质上受到限制的值已经是 CHAR(1),因此归一化并没有给我们带来太多好处。不幸的是,大多数查询最终都会针对愚蠢的 varchar(30) 甚至是 varchar(100) 字段运行。
    • 您是否检查过索引 CHAR(1) 字段是否对您有用?表扫描可能会更快......这肯定会加快插入速度。
    • 我必须确认一下,但我相信我们已经出于这个原因取出了 CHAR(1) 字段上的所有索引。数据基本上是物流和库存类型的东西。托运人、产品描述、城市、州 - 但种类繁多。
    • 嗯...我会试一试创建表的事情,但如果 MyISAM 在重新索引方面表现不佳 - 哇。这种密封交易几乎可以转移到其他任何东西。我们做得很好,不是很好,但在当天查询时间还可以。这是历史插入与历史查询时间的权衡。
    【解决方案4】:

    我不清楚分析处理有多复杂。在我看来,处理 50 万条记录应该不是什么大问题,就分析处理而言,它是一个小记录集。

    即使它是一项复杂的工作,如果你可以让它过夜完成(因为这是一个日常过程,正如我从你的帖子中理解的那样),它应该仍然足够。

    关于结果表,我不会减少表的索引。同样,您可以在夜间进行加载,包括刷新索引,并让生成的更新数据集在早上准备好使用,与原始表(非索引)相比,访问速度更快。

    我看到 PosgreSQL 在类似数据仓库的环境中使用,在我描述的设置(夜间数据转换工作)上工作并且没有性能投诉。

    【讨论】:

    • 静态的日常处理(包括脚本/数据库时间)实际上运行得非常快。它上传平面文件,移动一些表格,计算的统计信息(约 100 个差异数字),生成报告表,从统计信息生成 PNG 图表,从图表和统计信息生成 PDF 并在约 3 分钟内通过电子邮件发送它们。 :)
    • 历史的情况是个问题 - 50 万不是问题,4 亿,更多的问题。
    • 那是另一回事,您可能需要对历史表的​​分区支持。索引是肯定的。
    【解决方案5】:

    我会选择 PostgreSQL。例如,您需要分区表,这些表至少从 2005 年开始就在稳定的 Postgres 版本中 - 在 MySQL 中这是一个新事物。我听说过stability issues in new features of 5.1。使用 MyISAM,您没有参照完整性,事务和并发访问受到很大影响 - 阅读此博客条目“Using MyISAM in production”了解更多信息。

    而且 Postgres 在处理复杂查询时要快得多,这对您的 #6 很有好处。 还有一个非常活跃和乐于助人的mailing list,您甚至可以免费获得core Postgres developers 的支持。不过它有一些gotchas

    【讨论】:

      【解决方案6】:

      Infobright 的人似乎在做一些有趣的事情:

      http://www.infobright.org/

      --psj

      【讨论】:

        【解决方案7】:

        如果由于成本问题不考虑使用 Oracle,则可以免费使用 Oracle Express Edition(就像啤酒一样)。它有大小限制,但如果您不将历史记录保存太久,则不必担心。

        【讨论】:

        • Oracle express 甚至无法满足我需要的数据量。
        【解决方案8】:

        检查您的硬件。你在最大化 IO 吗?您是否正确配置了缓冲区?您的硬件尺寸是否正确?用于缓冲和快速磁盘的内存是关键。

        如果索引过多,插入速度会大大降低。

        你是如何进行插入的?如果您为每个 INSERT 语句做一条记录:

        INSERT INTO TABLE blah VALUES (?, ?, ?, ?)
        

        并调用它 500K 次,你的表现会很糟糕。我很惊讶它会在几个小时内完成。使用 MySQL,您可以一次插入数百或数千行:

        INSERT INTO TABLE blah VALUES
          (?, ?, ?, ?),
          (?, ?, ?, ?),
          (?, ?, ?, ?)
        

        如果您对每个 Web 请求进行一次插入,则应考虑登录到文件系统并在 crontab 上进行批量导入。我过去曾使用这种设计来加快插入速度。这也意味着您的网页不依赖于数据库服务器。

        使用LOAD DATA INFILE 导入CSV 文件也快得多。见http://dev.mysql.com/doc/refman/5.1/en/load-data.html

        我可以建议的另一件事是提防 SQL 锤子——你可能没有 SQL 钉子。您是否考虑过使用PigHive 之类的工具来为您的报告生成优化的数据集?

        编辑

        如果您在批量导入 50 万条记录时遇到问题,则需要在某个地方做出妥协。我会在您的主表上删除一些索引,然后为每个报告创建优化的数据视图。

        【讨论】:

        • 数据最初是通过加载文件加载到数据库中的——速度非常快。进入历史表是一个插入历史选择列...从当前。
        • 它肯定是减慢插入速度的索引,但我们不能删除那些 - 否则历史查询太慢了。我们不会从网页加载任何数据。缓慢的插入是从一个表到另一个表。
        • 我没有尝试过 Pig 或 Hive,我将不得不进行调查。我很确定我们的解决方案将不得不依赖于 SQL - 整个分析数据库太集成到其他几个系统中,无法承受如此大的变化。
        • 您可以使用 pig/hive 将数据预处理为每个报告的优化格式。那时你基本上是在做一个迷你 ETL 过程。
        【解决方案9】:

        您是否尝试过使用 myisam_key_buffer 参数?对索引更新速度非常重要。

        此外,如果您有日期、id 等相关列的索引,您可以这样做:

        INSERT INTO archive SELECT .. FROM current ORDER BY id (or date)
        

        这个想法是按顺序插入行,在这种情况下索引更新要快得多。当然,这只适用于与 ORDER BY 一致的索引...如果您有一些相当随机的列,那么这些将无济于事。

        但强烈考虑 PostgreSQL。

        你绝对应该测试它。

        似乎PostgreSQL可以通过部分索引和基于函数的索引来帮助我们。

        是的。

        我已经阅读了几十篇关于两者之间差异的文章,但大多数都是旧的。 PostgreSQL 长期以来一直被贴上“更高级但更慢”的标签——将 MySQL 5.1 与 PostgreSQL 8.3 进行比较还是普遍情况还是现在更平衡?

        这取决于。与任何数据库一样,

        • 如果您不知道如何配置和调整它,它会很慢
        • 如果您的硬件不能胜任这项任务,它会很慢

        一些非常了解 mysql 并想尝试 postgres 的人没有考虑到他们需要重新学习一些东西并阅读文档这一事实,因此对配置非常糟糕的 postgres 进行了基准测试,这可能是很慢。

        对于网络使用,我在低端服务器(Core 2 Duo,SATA 磁盘)上使用我编写的自定义基准论坛对配置良好的 postgres 进行了基准测试,它每秒吐出超过 4000 个论坛网页,使数据库服务器的千兆以太网链路饱和。因此,如果您知道如何使用它,它可能会非常快(由于并发问题,InnoDB 速度要慢得多)。 “MyISAM 对小型简单选择更快”是完全公牛,postgres 将在 50-100 微秒内完成“小型简单选择”。

        现在,为了您的使用,您不必关心它;)

        您关心数据库计算 Big Aggregates 和 Big Joins 的方式,并且具有良好 IO 系统的正确配置的 postgres 通常会在这些方面胜过 MySQL 系统,因为优化器更智能,并且有更多的连接/聚合类型可供选择。

        我最担心的是缺少 INSERT IGNORE。我们在构建一些处理表时经常使用它,这样我们就可以避免将多条记录放入两次,然后不得不在最后做一个巨大的 GROUP BY 来删除一些重复。我认为它的使用频率很低,因此缺乏它是可以容忍的。

        您可以使用 GROUP BY,但如果您只想将不存在的记录插入表中,您可以这样做:

        INSERT INTO target SELECT .. FROM source LEFT JOIN target ON (...) WHERE target.id IS NULL
        

        在您的用例中,您没有并发问题,因此效果很好。

        【讨论】:

          猜你喜欢
          • 2015-03-17
          • 2012-04-07
          • 1970-01-01
          • 1970-01-01
          • 2014-05-13
          • 1970-01-01
          • 1970-01-01
          • 2013-01-08
          • 2016-08-06
          相关资源
          最近更新 更多