InnoDB 引擎是否跟上内存引擎的速度?

Que*_*low 5 mysql innodb performance memory

我正在探索 MySQL 5.5.18 版中不同数据库引擎的效率,以查看哪个最适合与 500 万行数据集的范围查询一起使用:

SELECT P.col1, P.col2, P.col3, P.col4, P.col5, P.col6, P.col7, P.col8, P.col9
 , P.col10, P.col10 * R.col3 as 'combi' 
FROM PRODUCT P INNER JOIN RATE R ON R.col2 = P.col2 
WHERE P.col3 = 'y' 
 AND P.col4 >= 1000 
 AND P.col5 >= 5 
 AND P.col6 BETWEEN 10 AND 100 
 AND P.col7 >= 0 
 AND P.col8 >= 7 
 AND P.col9 >= NOW() 
 AND P.col10 * R.col3 BETWEEN 50 AND 80
ORDER BY P.col8 DESC LIMIT 100;
Run Code Online (Sandbox Code Playgroud)

基于对Stackoverflow 的一些讨论,我了解到我可以通过将InnoDB参数设置为innodb_buffer_pool_size大于数据集的大小来将数据库加载到 RAM 中。调整这个参数后,我很失望的是,查询的速度在大多数情况下都不比MyISAM快(平均 3s 对 0.3s),比Memory慢 100 倍。

进一步查阅MySQL手册,说明了以下两点:

  • InnoDB 维护一个称为缓冲池的存储区域,用于在内存中缓存数据和索引。
  • 缓冲池越大,InnoDB就越像内存数据库,从磁盘读取数据一次,然后在后续读取期间从内存访问数据。

在我看来,这innodb_buffer_pool_size更像是缓存重复查询的结果,而不是提供运行查询的数据库的热副本。我的理解是正确的还是我错过了一些可以让 InnoDB 引擎匹配内存引擎的东西,对于非重复范围查询(如上面的查询),性能方面?

更新:

Frederick Cheung 正确地指出 InnoDB 缓冲池确实缓存了数据库的热副本。我错过的是在 Rolando 提供的链接中找到的加载程序:

在每次启动时扫描表的全部内容(所有数据和索引页)以将内容预加载到内存中SELECT * FROM <table> ORDER BY <pkey fields>,每个表,然后是SELECT <indexed fields> FROM <table> ORDER BY <index fields>每个索引。

经过进一步测试,我能够将查询时间(0.3 到 1.0 秒)降低到与MyISAM引擎相当的水平。但这仍然比使用内存引擎获得的速度慢七倍左右。

由于两个引擎都从 RAM 查询数据库,有人能告诉我为什么InnoDB引擎仍然无法跟上内存引擎的速度吗?

Rol*_*DBA 7

具有讽刺意味的是,我之前回答了一个关于InnoDB 与 MEMORY 存储引擎的问题

您必须考虑关于MEMORY 存储引擎的一些非常奇怪的东西。

每次有 INSERT、UPDATE 和 DELETE 时,MEMORY 表都会执行全表锁定。

MEMORY 表仍然会触发少量磁盘 I/O,因为 MEMORY 表的 .frm 文件是一个磁盘文件,只要该表存在,并且此后的查询解析就必须在每个查询中引用该文件

MEMORY 表的默认索引类型是 HASH 索引而不是 BTREE。如果您忘记声明USING BTREE,则所有范围搜索都会变成表扫描。HASH 索引不太适合用于完成范围查询的索引。您在问题正文中的查询很快就会受到影响。

即使您使用该USING BTREE子句在 MEMORY 表中创建索引,RAM 中的 BTREE 索引也会以 O(log n) 的速度增长,因此再次期待磁盘 I/O 以检查 .frm 文件中的索引定义加上 O(log n)页面访问的运行时间。

使用 MEMORY 存储引擎时要考虑的另一件疯狂的事情是:如果您尝试连接 MEMORY 表和 InnoDB 表,则结果锁定行为默认为最坏的锁定行为,在这种情况下是全表锁定。

警告

其他人在 2011 年 3 月回答过这样的问题

这里有一个关于全内存数据库好坏的原因:让 MySQL 内存存储引擎使用 512 GB 的 RAM 是否可行?


小智 4

MySQL 存储引擎包括处理事务安全表的引擎和处理非事务安全表的引擎以及许多其他引擎。MySQL 通过其可插拔存储引擎架构来实现这一点。\n两者都有一些优点和缺点。我们可以将核心功能/性能分为四个区域;

\n\n
    \n
  1. 支持的字段和数据类型
  2. \n
  3. 锁定类型
  4. \n
  5. 索引和
  6. \n
  7. 交易
  8. \n
\n\n

有些引擎具有独特的功能,也可以帮助您做出决定。

\n\n

MEMORY存储引擎将 所有数据存储在内存中;一旦 MySQL 服务器关闭,存储在 MEMORY 数据库中的任何信息都将丢失。但是,单个表的格式会被保留,这使您能够创建可用于存储信息以便快速访问的临时表,而无需在每次启动数据库服务器时重新创建这些表。

\n\n

长期使用 MEMORY 存储引擎通常不是一个好主意,因为数据很容易丢失。但是,如果您有 RAM 来支持您正在使用的数据库,那么使用基于 MEMORY 的表是对大型数据集运行复杂查询并从性能提升中受益的有效方法。

\n\n

使用 MEMORY 表的最佳方法是使用 SELECT 语句从基于磁盘的原始表中选择更大的数据集,然后对该信息进行子分析以获取所需的特定元素。

\n\n

InnoDB引擎支持 MyISAM 引擎的所有数据库功能(以及更多),并且还添加了完整的事务功能(具有完整的 ACID(原子性、一致性、隔离性和持久性)合规性)和数据的行级锁定。

\n\n

InnoDB系统的关键是数据库、缓存和索引结构,其中索引和数据都缓存在内存中以及存储在磁盘上。这可以实现非常快速的恢复,甚至可以处理非常大的数据集。通过支持行级锁定,您可以将数据添加到 InnoDB 表中,而无需引擎在每次插入时锁定表,这可以加快数据库中信息的恢复和存储速度。

\n\n

如果您愿意(并且能够)为您的服务器配置 InnoDB 设置,那么我建议您花时间优化您的服务器配置,然后使用 InnoDB 引擎作为默认引擎。

\n\n

有关更多详细信息,请参阅本文:MySQL 存储引擎 \xe2\x80\x93 其局限性和比较尝试

\n