数据库内存和磁盘工作分配

Database memory and disk work assignation

我正在阅读有关索引和索引策略的电子书章节,其中许多方面我已经知道,但我坚持使用 InnoDB 中的聚簇索引,引用如下:

Clustering gives the largest improvement for I/O-bound workloads. If the data fits in memory the order in which it’s accessed doesn’t really matter, so clustering doesn’t give much benefit.

我相信这是事实,但我该如何猜测数据是否适合内存?数据库如何决定何时处理内存中的数据,何时不处理?

假设我们有一个 table EmpID, Name, 和 Phone 填充了 100 000 条记录

如果,举个例子,我将聚簇索引放在ID列上,执行这个查询

SELECT * FROM Employee;

我怎么知道这是否会利用聚簇索引的优势?

它与此线程有某种关系 Difference between In memory databases and disk memory database

但我不确定数据库的行为方式

您的示例可能是 20MB。

"In memory" 真正的意思是 "in the InnoDB buffer_pool",其大小由 innodb_buffer_pool_size 控制,应该设置为 available RAM 的大约 70% .

如果您的查询命中磁盘而不是在 buffer_pool 中找到所有 缓存,它将 运行(这只是一个经验法则)慢 10 倍。

您在 "clustered index" 上所说的内容具有误导性。让我扭转局面...

  • InnoDB 真的需要 PRIMARY KEY.
  • PK 是(根据 MySQL 中的定义)UNIQUE
  • 一个table.
  • 只能有一个PK
  • PK 可以是 "natural" 密钥,由 'naturally' 有效的一个(或多个)列组成。
  • 如果您没有 "natural" 选择,请使用 id INT UNSIGNED NOT NULL AUTO_INCREMENT
  • PK和数据存放在同一个BTree中。 (实际上是一个 B+ 树。) 导致 "the PK is clustered with the data".

真正的问题不是某些东西是否集群,而是它是否缓存在 RAM 中。 (记住 10x RoT。)

  • 如果 table 很小,它将保留在缓存中(一旦它的所有块都被触及),从而避免磁盘命中。
  • 如果巨大 table 的某个子集是 "hot",它将倾向于保留在缓存中。
  • 如果您必须访问巨大的 table "randomly",您将因大量磁盘命中而速度变慢。 (当使用 UUID 作为 PRIMARY KEY 其他类型的 INDEX 时会发生这种情况。)

How the database decide when to process the data in-memory, and when not?

那也是 'wrong'。所有处理都在内存中。在逐块的基础上,table 的片段和索引被移入/移出 buffer_pool。一个块(在 InnoDB 中)是 16KB。 buffer_pool 是这样的块的 "cache"。

SELECT * FROM Employee;

简单,但成本高。它是这样运作的:

  1. "Open" table Employee(如果尚未打开 - 不同的 'cache' 处理此问题)。
  2. 转到 table 的开头。这涉及向下钻取 PK 的 BTree 的左侧到第一个叶节点(块)。如果尚未缓存,则将其提取到 buffer_pool 中。
  3. 读取一行 -- 这将在那个叶节点中。
  4. 阅读下一行 -- 这 可能 在同一块中。如果没有,获取 'next' 块(必要时从磁盘读取)。
  5. 重复第 4 步,直到完成 table。

如果你有 WHERE 子句,事情会变得更有趣。然后就看是PK还是其他INDEX

等等等等