【问题标题】:Very large database, very small portion most being retrieved in real time非常大的数据库,非常小的部分大部分是实时检索的
【发布时间】:2010-05-20 17:30:49
【问题描述】:

我有一个有趣的数据库问题。我有一个大小为 150GB 的数据库。我的内存缓冲区是 8GB。

我的大部分数据很少被检索,或者主要由后端进程检索。我非常希望保留它们,因为某些功能需要它们。

其中一些(即一些表,以及某些表的一些可识别部分)经常以面向用户的方式使用

如何确保后者始终保存在内存中? (这些空间绰绰有余)

更多信息: 我们在 Ruby on rails 上。数据库是 MYSQL,我们的表是使用 INNODB 存储的。我们将数据分片到 2 个分区。因为我们正在对其进行分片,所以我们使用 JSON Blob 存储大部分数据,同时仅索引主键

更新 2 棘手的是,数据实际上同时用于后端进程以及面向用户的功能。但后者的访问频率要低得多

更新 3 这些天有些人评论说 8Gb 是玩具。我同意,但是如果有更智能、更有效的解决方案,仅仅增加数据库的大小就是纯粹的懒惰

【问题讨论】:

  • 这个问题有点含糊。您没有向我们提供有关架构设计的任何详细信息,也没有指定您正在使用的技术(数据库、编程平台等)。我怀疑对这个问题的任何有意义的答案都将针对这些技术你正在使用。
  • 谢谢!我已根据您的评论更新了问题
  • 如果一切都失败了,我想你总是可以复制数据库,所以后端进程访问一台服务器,用户访问另一台服务器。这应该可以防止他们互相踩踏,尽管这样你就必须在数据更新时保持两台服务器同步......
  • 对Update 3不能再认同了。当数据150TB,内存用完时,也不能解决同样的问题。

标签: database performance database-design memory database-administration


【解决方案1】:

这就是我们拥有数据仓库的原因。将这两件事分成 (a) 单独的数据库或 (b) 一个数据库中的单独模式。

  1. 用于即时访问的最新数据正在更新中。

  2. 历史事实数据,用于分析,未更新。

150Gb 不是很大,单个数据库可以处理少量实时数据和大量历史记录。

使用“周期性”ETL 过程将数据从活动数据库中取出,非规范化为星型模式并加载到历史数据仓库中。

【讨论】:

  • 您能否更详细地说明一个数据库中的“单独架构”的含义?我对此不太熟悉 - 谢谢!
  • @S. Lott:从后端流程使用的数据是用于报告/数据挖掘还是可能只是非实时处理的问题中,目前尚不清楚。如果他们正在处理历史数据,则 100% 同意使用 DW 而不是处理事务数据库。
  • 我同意,试图为分析需求和低延迟 Web 需求提供单一来源通常会导致两者都不是最佳的。
  • 感谢您的精彩提示!目前,数据仓库对我来说有点过分了。我认为我需要的可以通过给 mysql 一些关于缓存什么的提示来实现,然后分解一些表并告诉 mysql 不要缓存这些
  • @ming yew:如果你做错了,“数据仓库”可能会矫枉过正。将您的数据分为“活动”和“历史”是简单、快速、高效的,并且仍然是一种数据仓库。
【解决方案2】:

如果在面向客户的表中使用的列数很少,您可以为查询中使用的所有列创建索引。这并不意味着所有数据都保留在内存中,但它可以使查询更快。其响应时间的交易空间。

【讨论】:

    【解决方案3】:

    这需要 memcached!我推荐使用 cache-money,一个很棒的 ActiveRecord 直写缓存库。 The ngmoco branch 支持为每个模型启用缓存,因此您只能缓存那些您知道要保留在内存中的内容。

    您也可以在控制器操作或模型挂钩中使用 $cache.set/get/expire 调用手动进行缓存。

    【讨论】:

    • 谢谢!这是一个很好的提示。你知道缓存钱是否适用于分片数据库吗?我们没有使用 activerecord 本身
    • 是的,我很高兴在处理我的分片/复制设置的 db_charmer 库之上使用 cache-money [1]。 YMMV 取决于您如何连接到 AR 进行分片——如果您遇到问题,很乐意提供指向适当缓存货币内部结构的指针。 [1]github.com/kovyrin/db-charmer
    【解决方案4】:

    使用 MySQL,正确使用Query Cache 会将频繁查询的数据保留在内存中。您可以使用 SQL_NO_CACHE 关键字向 MySQL 提供不缓存某些查询(例如来自后端进程)的提示。

    如果后端进程正在访问历史数据或访问数据以用于报告目的,请务必遵循 S. Lott 的建议,创建一个单独的数据仓库并进行查询。如果数据仓库在短期内无法完成,您可以将事务数据库复制到不同的服务器并在那里执行查询(数据仓库为您提供了更多的灵活性和能力,所以尽可能走这条路)

    更新:

    更新 2:

    我通过 MySQL 支持确认,在 innodb 缓冲池中没有选择性缓存某些表等的机制。

    【讨论】:

    • “SQL_NO_CACHE”看起来非常有用。它可以用于 1) 避免缓存表吗? 2) 避免根据条件缓存 SELECT 查询?让我知道这是否应该是一个单独的问题。顺便说一句 - 你非常乐于助人 - 谢谢!
    • @Ming:您可以使用它来显式避免缓存查询或显式请求缓存,具体取决于 query_cache_type 的设置。但是,我不知道将某些表保留在 innodb_buffer_pool 中的方法,这本质上是您的问题 1。添加了一些链接以获取有关您的问题 2 的更多详细信息。
    • 查询缓存不做任何事情来将数据保存在内存中,如果一个新的查询查询相同的数据,它什么也不做。在许多情况下,将内存专用于 innodb 缓冲池而不是查询缓存会更有效。
    • @MarkR:查询缓存将重复查询的数据保存在内存中。这就是缓存的重点。 innodb 缓冲池的问题是低优先级的后台进程正在将事物踢出 innodb 缓冲池。理想情况下,他会想找到一种方法来标记哪些表或表的部分符合 innodb 缓冲池的条件,但我不知道如何实现这一点。我知道的下一个最好的事情是调整查询缓存,以便至少来自在线系统的频繁查询在缓存中。由于 RAM 远小于数据,innodb 缓冲区可能会丢失。
    • 缓冲区缓存是你想要的,而不是查询缓存。
    【解决方案5】:

    那么,问题出在哪里?

    首先,今天 150GB 不是很大。那是10年前的事了。

    其次,任何非完全废话的数据库系统都会将您的内存用作缓存。如果缓存足够大(与正在使用的数据量相比),它将是有效的。如果没有,您唯一能做的就是获得更多内存(因为,抱歉,8gb 的内存对于现代服务器来说非常低 - 2 年前还低)。

    您不必为有效使用内存做任何事情。至少不是在商业级数据库上——也许 mysql 很烂,但我不会这么认为。

    【讨论】:

    • 嗯,问题是大量不同的数据位经常被后端进程访问,交换出我需要在内存中的数据,因为它是面向用户的。
    • 后端进程通常比用户更有耐心。他们将等待从磁盘检索数据。
    • 最重要的是。要么你只接触部分数据,要么不接触。如果后端进程开始表扫描,那么基本上 - 你需要更多内存。观点。没有什么帮助。更多内存(那么像真正的服务器一样的 32gb 呢?)和顶部的 FAST 磁盘子系统。如今,8gb 是数据库的玩具类别。
    • 8Gb 这些天是玩具 >> 我同意,但是如果有一个更智能、更有效的解决方案,只是增加数据库的大小是纯粹的懒惰你不会在你所做的每一件事上都“增加数据库”
    • innodb 缓冲区缓存是由聪明、高效的开发人员编写的智能、高效、调整良好的解决方案。没有什么懒惰的。如果您想绝对保证某些表将始终在缓冲区缓存中,只需定期读取它们即可。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-10
    • 2016-11-23
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    相关资源
    最近更新 更多