数据库内存和磁盘工作分配
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 Emp 列 ID, 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;
简单,但成本高。它是这样运作的:
- "Open" table
Employee
(如果尚未打开 - 不同的 'cache' 处理此问题)。
- 转到 table 的开头。这涉及向下钻取 PK 的 BTree 的左侧到第一个叶节点(块)。如果尚未缓存,则将其提取到 buffer_pool 中。
- 读取一行 -- 这将在那个叶节点中。
- 阅读下一行 -- 这 可能 在同一块中。如果没有,获取 'next' 块(必要时从磁盘读取)。
- 重复第 4 步,直到完成 table。
如果你有 WHERE
子句,事情会变得更有趣。然后就看是PK还是其他INDEX
等等等等
我正在阅读有关索引和索引策略的电子书章节,其中许多方面我已经知道,但我坚持使用 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 Emp 列 ID, 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;
简单,但成本高。它是这样运作的:
- "Open" table
Employee
(如果尚未打开 - 不同的 'cache' 处理此问题)。 - 转到 table 的开头。这涉及向下钻取 PK 的 BTree 的左侧到第一个叶节点(块)。如果尚未缓存,则将其提取到 buffer_pool 中。
- 读取一行 -- 这将在那个叶节点中。
- 阅读下一行 -- 这 可能 在同一块中。如果没有,获取 'next' 块(必要时从磁盘读取)。
- 重复第 4 步,直到完成 table。
如果你有 WHERE
子句,事情会变得更有趣。然后就看是PK还是其他INDEX
等等等等