【问题标题】:How do I make a MySQL database run completely in memory?如何让 MySQL 数据库完全在内存中运行?
【发布时间】:2012-05-28 09:00:38
【问题描述】:

我注意到我的数据库服务器支持内存数据库引擎。我想让一个我已经运行 InnoDB 的数据库完全在内存中运行以提高性能。

我该怎么做?我探索了 PHPMyAdmin,但找不到“更改引擎”功能。

【问题讨论】:

  • 你应该首先了解你在那里做什么。使用内存引擎有一定的含义。
  • 在内存中运行意味着一旦您重新启动 MySQL 守护程序(或崩溃),数据就会被擦除,您最好使用 MySQL 的 query_cache 或用于缓存结果的 memcached
  • 我不确定这是否是您想要的。您的性能问题究竟是什么?
  • 不太可能。添加/调整您的索引。合并查询以提高效率。像这样的东西通常更有效,应该是你的初始方法。
  • 这对于在带有数据库的 POS 软件上进行许多测试非常方便。测试结束后,不再需要数据库。为了运行所有测试,稍后会加载和验证 500 个数据库......在 RAM 中可能会节省大量时间。

标签: mysql database


【解决方案1】:

假设您了解使用 cmets 和 here 中提到的 MEMORY 引擎的后果,以及您可以通过搜索找到的其他一些引擎(无事务安全、锁定问题等) - 您可以继续如下:

MEMORY 表的存储方式与 InnoDB 不同,因此您需要使用导出/导入策略。首先使用SELECT * FROM tablename INTO OUTFILE 'table_filename' 将每个表单独转储到一个文件中。创建 MEMORY 数据库并使用以下语法重新创建您将使用的表:CREATE TABLE tablename (...) ENGINE = MEMORY;。然后,您可以使用LOAD DATA INFILE 'table_filename' INTO TABLE tablename 为每个表导入数据。

【讨论】:

  • 这实际上并没有说明如何创建内存数据库或表。
  • 至于@INTPnerd 的观点,在重新创建表时,使用语法:CREATE TABLE someTable (...) ENGINE = MEMORY;
  • 你不建议使用mysqldump有什么原因吗?我只是试了一下,没有发现任何问题(不过只是一个非常快速的测试)。
  • @BetLamed 使用 mysqldump 的输出恢复将起作用,但比批量导入要慢得多,因为每个 INSERT 都需要单独运行(产生 INSERT 事务的开销)。批量导入消除了这一点,并且对于大量数据可以预期会更快。
【解决方案2】:

如果您的数据库足够小(或者如果您添加了足够的内存),您的数据库将有效地在内存中运行,因为您的数据将在第一次请求后被缓存。

更改数据库表定义以使用内存引擎可能比您需要的要复杂。

如果您有足够的内存来使用 MEMORY 引擎将表加载到内存中,那么您就有足够的内存来调整 innodb 设置以缓存所有内容。

【讨论】:

    【解决方案3】:

    Memory Engine 不是您正在寻找的解决方案。您首先会丢失访问数据库的所有内容(即 ACID)。

    这里有一些更好的选择:

    1. 不要使用连接 - 很少有大型应用程序会这样做(例如 Google、Flickr、NetFlix),因为它不适合大量连接。

    LEFT [OUTER] JOIN 可以比等效的子查询更快,因为 服务器可能能够更好地优化它——事实并非如此 仅针对 MySQL 服务器。

    -The MySQL Manual

    1. 确保要查询的列具有索引。使用 EXPLAIN 确认它们正在被使用。
    2. 为索引使用和增加 Query_Cache 和内存空间,以将它们放入内存并存储频繁的查找。
    3. 非规范化架构,尤其是对于简单连接(即从 barMap 获取 fooId)。

    最后一点是关键。我曾经喜欢联接,但后来不得不在几张 100M+ 行的表上运行联接。不好。最好将您要加入的数据插入到该目标表中(如果不是太多)并查询索引列,您将在几毫秒内得到您的查询。

    我希望这些帮助。

    【讨论】:

    • 最后一点可能对性能很有帮助,但如果使用不当,它可能会成为数据一致性和维护的杀手。触发更新或类似的缓存复制策略可以提供帮助,但缓存非规范化数据的方式不应该被认为是理所当然的......
    • @PinnyM 好点。这是一个人必须决定什么是最重要的。 RDBMS 非常适合原子性和一致性,但不适用于扩展和性能,尤其是连接。 6NF(Star Schema)很正常,但加入快乐。您仍然可以以规范化的方式将数据保留在某些表中,并使用触发器和计划任务从规范化表(读/写)更新非规范化(只读)表。
    • 1 和 4 是有史以来最糟糕的建议。
    • @Darwin 感谢投反对票。选择一致性或规模。对于数十亿行,一致性通常不值得开销,具体取决于您的用例(例如,就像我在工作中使用的所有 Col 存储一样)。
    • @JosephLust 你是对的,“选择一致性或规模”。大约 99% 的数据库最好具有一致性。大多数开发人员从未接触过大型数据库。大我的意思是不能以合理的价格将它保存在内存中。我相信您今天可以以合理的价格获得 0.5 到 1 TB 内存的服务器。
    【解决方案4】:

    可以考虑 MySQL Cluster 来代替 Memory 存储引擎。据说它提供了类似的性能,但支持磁盘支持的操作以提高耐用性。我没有尝试过,但它看起来很有前途(并且已经开发了很多年)。

    You can find the official MySQL Cluster documentation here.

    【讨论】:

      【解决方案5】:

      “我该怎么做?我探索了 PHPMyAdmin,但找不到“更改引擎”功能。”

      直接回答您的这部分问题,您可以发出ALTER TABLE tbl engine=InnoDB;,它会在适当的引擎中重新创建表。

      【讨论】:

        【解决方案6】:

        还可以将 MySQL 数据目录放在 tmpfs 中,从而加快数据库的写入和读取调用。这可能不是最有效的方法,但有时您不能只更改存储引擎。

        这是我的 MySQL 数据目录的 fstab 条目

        none            /opt/mysql/server-5.6/data  tmpfs   defaults,size=1000M,uid=999,gid=1000,mode=0700          0       0
        

        您可能还想查看 innodb_flush_log_at_trx_commit=2 设置。也许这会充分加速你的 MySQL。

        innodb_flush_log_at_trx_commit 更改 mysql 磁盘刷新行为。当设置为 2 时,它只会每秒刷新一次缓冲区。默认情况下,每次插入都会导致刷新,从而导致更多的 IO 负载。

        【讨论】:

        • 您可能还想看看 libeatmydata。它可以防止 fsync 和较旧的同步调用,从而加速应用程序。 flamingspork.com/projects/libeatmydata (apt-get install eatmydata ;eatmydata /etc/init.d/mysql restart)
        • 我正在考虑将整个 mysql 放在内存中,并使用另一个 mysql 实例来复制和持久化数据。当然,假设我可以处理由于复制延迟而导致数据丢失的风险。
        • @Jotschi 给我的链接是 404s
        【解决方案7】:

        其他想法:

        Ramdisk - 设置 MySQL 用作 RAM 磁盘的临时驱动器,非常容易设置。

        memcache - memcache 服务器很容易设置,用它来存储你的查询结果 X 时间。

        【讨论】:

        • 它也有一个 Linux 版本。很好的推荐。投票赞成!!!
        猜你喜欢
        • 1970-01-01
        • 2021-02-01
        • 2011-03-06
        • 2022-06-13
        • 2018-01-28
        • 1970-01-01
        • 2011-01-28
        • 1970-01-01
        • 2022-01-16
        相关资源
        最近更新 更多