【问题标题】:Database memory and disk work assignation数据库内存和磁盘工作分配
【发布时间】:2015-11-10 18:09:05
【问题描述】:

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

集群对 I/O 密集型工作负载的改进最大。如果 数据适合内存访问它的顺序不 真的很重要,所以集群并没有带来太多好处。

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

假设我们有一个表 Emp,其中 IDNamePhone 列填充了 100 000记录

如果,例如,我将聚集索引放在 ID 列上,并执行此查询

SELECT * FROM Employee;

我如何知道这是否会利用聚集索引带来的好处?

它在某种程度上与这个线程有关 Difference between In memory databases and disk memory database

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

【问题讨论】:

    标签: mysql memory-management innodb clustered-index


    【解决方案1】:

    您的示例可能是 20MB。

    “在内存中”真正的意思是“在 InnoDB 缓冲池中”,其大小由innodb_buffer_pool_size 控制,应该设置为 可用 RAM 的 70% 左右。

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

    您在“聚集索引”上所说的内容具有误导性。让我扭转局面……

    • InnoDB 确实需要PRIMARY KEY
    • PK 是(根据 MySQL 中的定义)UNIQUE
    • 一个表只能有一个 PK。
    • PK 可以是一个“自然”键,由一个(或多个)“自然”工作的列组成。
    • 如果您没有“自然”的选择,请使用id INT UNSIGNED NOT NULL AUTO_INCREMENT
    • PK 和数据存储在同一个 BTree 中。 (实际上是一个 B+Tree。)导致“PK 与数据聚集在一起”。

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

    • 如果表很小,它将保留在缓存中(一旦所有块都被触及),从而避免磁盘命中。
    • 如果一个大表的某个子集是“热的”,它往往会留在缓存中。
    • 如果您必须“随机”访问一个巨大的表,您将因大量磁盘命中而导致速度变慢。 (当将 UUID 用作 PRIMARY KEY 其他类型的 INDEX 时,会发生这种情况。)

    数据库如何决定何时处理内存中的数据,何时不处理?

    那也是“错误的”。所有处理都在内存中。在逐块的基础上,表和索引的片段被移入/移出 buffer_pool。一个块(在 InnoDB 中)是 16KB。而buffer_pool就是这些块的“缓存”。

    SELECT * FROM Employee;
    

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

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

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

    等等等等

    【讨论】:

    • 我回答了你给的链接。
    猜你喜欢
    • 2014-11-06
    • 1970-01-01
    • 2010-11-29
    • 1970-01-01
    • 2010-10-17
    • 1970-01-01
    • 2012-03-24
    • 2015-09-20
    • 1970-01-01
    相关资源
    最近更新 更多