SSD 上的 Postgres 堆表性能

VB_*_*VB_ 5 mysql rdbms postgresql performance query-performance postgresql-performance

我已经阅读了相同架构/查询的 MySQL 和 PostgreSQL 之间的性能差异。. 它是否仍然与固态硬盘的外观有关?

那篇文章说 Postgres 更适合复杂查询和子查询,而对于通过 id 和顺序扫描进行的简单查询则更差。

对于某些查询,Postgres 更糟糕/更慢,因为每个表都是一个堆,意味着没有聚集索引,意味着行没有按主键在硬盘驱动器上物理排序。因此,如果您想从 Postgres 读取大部分记录(根据我的理解,通过 id) - 如果与 MySQL 相比,这将导致许多随机 I/O 和更差的性能。

问题:

  1. 但是SSD呢?Postgres 和 MySQL 的顺序读取性能是否相同?
  2. 在 RDBM 中使用 SSD 而不是 HHD 是否有意义?

更新:与 Rick James 的回答有关

  1. MySQL 使用Plan A和 Postgres 使用Plan B,对吗?
  2. Plan A表示聚集索引,对吗?该表按 物理排序lastName + firstName
  3. Plan A在 HDD 上的性能可能比Plan B在 SSD 上更好,因此 Postgres + SSD 不是灵丹妙药。查询聚集索引需要选择MySQL,对吗?
  4. 请详细了解 I/O 绑定是指哪些查询?在我的理解中any call to database == I/O bound operation

Ric*_*mes 5

“计算磁盘命中数。”

让我们构建一个简单的表并对其进行查询。然后让我们讨论两个数据库引擎将如何执行该查询。

我们有一个包含姓氏和名字的表格,以及其他内容。桌子很大;大到无法缓存在 RAM 中。查询需要查找具有给定姓氏和一些首字母的所有人:

SELECT * FROM tbl
    WHERE lastname = 'James'
      AND firstname LIKE 'R%';
Run Code Online (Sandbox Code Playgroud)

方案A:该表使用B+树按姓+名排序。操作是这样的:

  1. 找到第一行 (James,R)。这需要向下钻取深度可能为 4 的 B+Tree 的层。很可能这种树中的所有非叶节点都将保持缓存状态。但是叶节点不会(因为表的大小)。成本(到目前为止):非叶节点的磁盘命中为 0,叶节点的磁盘命中为 1。
  2. 通过 B+Tree 向前扫描。假设树中的典型块包含 100 条记录。假设有 300 个匹配的名称。成本:大约 3 次磁盘命中。

总成本:约 4 次磁盘命中。

方案B:有一个INDEX(lastname, firstname)to hash-pointer,然后指向数据。

  1. 遍历该索引以查找所有 300 个匹配名称。如果 INDEX 类似于 BTree,也就是大约 4 次磁盘命中。
  2. 对于 300 个名称中的每一个,在数据中进行哈希查找以获取SELECT *. 由于查找涉及散列,因此记录将分散。而且,由于我假设该表太大而无法缓存,因此查找记录需要进行 300 次以上的磁盘点击。

总成本:大约在 4 到 304 之间;让我们慷慨一点,说 100。

此外,假设整个查询有 1 毫秒的 CPU。假设 HDD 磁盘命中为 10 毫秒,SDD 磁盘命中为 0.5 毫秒。

Plan             HDD (ms)   SDD (ms)   RAM (ms, if the table were fully cached)
Plan A: B+Tree    41          3          1
Plan B: Hash    1001         51          1
Run Code Online (Sandbox Code Playgroud)

(旁注:在任何数据库引擎中对 UUID 进行索引就像丢弃 BTree 并仅使用 Hash。)

在 SSD 变得与 RAM 一样快之前,将存在性能差距。

作为您的问题 2(使用 SSD 是否有意义):如果您受 I/O 限制,那么是的。否则,它可能不会“划算”。RDBMS 尝试缓存所有内容,从而消除 I/O(用于读取);如果数据足够小,I/O 速度无关紧要。

另一方面,写入更有可能依赖于 I/O 速度。但这是另一个讨论(有类似的结论)。

回复问题更新:

  1. 披露:我对MyISAM非常熟悉;Plan A 非常接近 MySQL 的 InnoDB。我对Postgres非常陌生;我不知道B计划是否与它有关。
  2. 是的。
  3. 是的。
  4. 这取决于。一个SELECT需要它的一切在RAM中缓存:没有I / O。在设置为最大安全性的事务中写入:始终 I/O。并且有很多“介于两者之间”。