4

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

  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 来删除一些重复。我认为它的使用频率很低,以至于缺乏它是可以容忍的。

4

9 回答 9

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 好得多)

于 2009-04-03T13:03:00.380 回答
2

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

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

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

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

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

于 2009-04-03T22:49:02.813 回答
1

根据我的经验,对于非常简单的查询,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 更快,因为更新是对索引列的更新。

于 2009-04-03T05:25:35.113 回答
1

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

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

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

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

于 2009-04-03T06:31:09.730 回答
1

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

Postgres 在复杂查询上要快得多,这对你的 #6 有好处。还有一个非常活跃和有用的邮件列表,您甚至可以从核心 Postgres 开发人员那里免费获得支持。但它有一些问题

于 2009-04-03T09:19:34.303 回答
1

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

http://www.infobright.org/

--psj

于 2009-04-03T22:55:16.683 回答
0

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

于 2009-04-03T23:07:47.433 回答
0

检查你的硬件。你在最大化 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等工具为您的报告生成优化的数据集?

编辑

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

于 2009-04-04T01:24:41.113 回答
0

您是否尝试过使用 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 微秒内完成“小型简单选择”。

现在,为了您的使用,您不在乎;)

你关心你的数据库计算大聚合和大连接的方式,一个正确配置的具有良好 IO 系统的 postgres 通常会在这些系统上胜过 MySQL 系统,因为优化器更聪明,并且有更多的连接/聚合类型从中选择。

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

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

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

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

于 2011-05-03T10:25:27.423 回答