Redrock Postgres 文档
主页 切换暗/亮/自动模式 切换暗/亮/自动模式 切换暗/亮/自动模式 返回首页

IO - DataFileRead

当由于数据页在共享内存中不可用,连接等待后端进程从存储中读取所需缓冲区页时,会发生 DataFileRead 事件。

上下文

所有查询和数据处理 (DML) 操作都会访问缓冲区中的页面。可以诱导读取的语句包括 SELECTUPDATEDELETE。例如,UPDATE 可以从表或索引中读取页面。如果请求或更新的页面不在共享缓冲区中,则此读取可能会导致 DataFileRead 事件。

由于共享缓冲区是有限的,所以它可以填满。在这种情况下,对不在内存中的页面的请求会强制数据库从磁盘中读取数据块。如果 DataFileRead 事件频繁发生,您的共享缓冲区可能太小,从而无法容纳您的工作负载。对于读取大量不适合缓冲区的行的 SELECT 查询,此问题很严重。有关缓冲区的更多信息,请参阅共享缓冲区

等待次数增加的可能原因

DataFileRead 事件的常见原因包括以下各项:

  • 连接激增

    您可能会发现多个连接生成相同数量的 DataFileRead 等待事件。在这种情况下,DataFileRead 事件可能会发生激增(突然大幅度增加)。

  • 执行顺序扫描的 SELECT 和 DML 语句

    您的应用程序可能正在执行新的操作。或者,现有的操作可能会因为新的执行计划而发生变化。在这种情况下,请查找具有更大的 seq_scan 值的表(特别是大表)。通过查询 pg_stat_user_tables 查找它们。要跟踪生成更多读取操作的查询,请使用插件 pg_stat_statements

  • 适用于大型数据集的 CTAS 和 CREATE INDEX

    我们把CREATE TABLE AS SELECT语句简称为 CTAS。如果您使用大型数据集作为源来运行 CTAS,或者在大型表上创建索引,则可能会发生 DataFileRead 事件。创建索引时,数据库可能需要使用顺序扫描读取整个对象。当页面不在内存中时,CTAS 会发生 DataFileRead 事件。

  • 导入大量数据

    当您的应用程序导入大量数据时,ANALYZE 操作可能会更频繁地发生。ANALYZE 进程可以由 Autoanalyze 启动程序触发,也可以手动调用。ANALYZE 操作可以读取表的子集。必须扫描的页数通过将 30 乘以 default_statistics_target 值进行计算。有关更多信息,请参阅 PostgreSQL 文档default_statistics_target 参数接受 1 到 10000 之间的值,其中原定设置值为 100。

  • 资源匮乏

    如果消耗了实例网络带宽或 CPU,DataFileRead 事件可能会更频繁地发生。

操作

根据等待事件的原因,我们建议采取不同的操作。

检查谓词筛选条件是否存在生成等待的查询

假设您确定了正在生成 DataFileRead 等待事件的特定查询。您可以使用以下方法识别它们:

  • 系统视图,例如扩展插件 pg_stat_statements 提供的视图
  • 系统视图 pg_stat_all_tables,如果它定期显示物理读取数量增加
  • pg_statio_all_tables 视图,如果它显示 _read 计数器正在增加

我们建议您确定这些查询的谓词(WHERE 子句)中使用了哪些筛选条件。请遵循以下准则:

  • 运行 EXPLAIN 命令。在输出中,确定使用的扫描类型。顺序扫描不一定表示存在问题。与使用筛选条件的查询相比,使用顺序扫描的查询自然会产生更多的 DataFileRead 事件。

    了解 WHERE 子句中列出的列是否已编入索引。如果没有,请考虑为此列创建索引。这种方法避免了顺序扫描并减少了 DataFileRead 事件。如果某个查询具有限制性筛选条件并且仍然生成顺序扫描,请评估是否使用了正确的索引。

  • 了解查询是否正在访问非常大的表。在某些情况下,对表进行分区可以提高性能,从而允许查询只读取必要的分区。

  • 检查联接操作的基数(总行数)。请注意您在筛选条件中为您的 WHERE 子句传递的值的限制性。如果可能,请优化查询以减少在计划的每个步骤中传递的行数。

尽量减少维护操作的影响

维护操作(例如 VACUUMANALYZE)非常重要。我们建议您不要将其关闭,因为您会找到与这些维护操作相关的 DataFileRead 等待事件。以下方法可以最大限度地减少这些操作的影响:

  • 在非高峰时段手动运行维护操作。此方法可防止数据库达到自动操作的阈值。
  • 对于非常大的表,请考虑对表进行分区。这种方法减少了维护操作的开销。数据库只访问需要维护的分区。
  • 当您导入大量数据时,请考虑禁用自动分析功能。

当以下公式为真时,系统会自动为表触发 Autoanalyze 功能。

pg_stat_user_tables.n_tup_ins > (pg_class.reltuples x autoanalyze_scale_factor) + autoanalyze_base_threshold

视图 pg_stat_user_tables 和目录 pg_class 有多个行。一行可以对应于表中的一行。这个公式假设 reltuples 适用于特定的表。参数 autoanalyze_scale_factor(原定设置为 0.20)和 autoanalyze_base_threshold(原定设置为 50 个元组)通常在全局范围内为整个实例设置。但是,您可以为特定表设置不同的值。

响应大量连接

您在监控数据库运行状态时,可能会发现数据库连接数指标激增。这种增加表示与数据库的连接数量有所增加。我们建议采取以下方法:

  • 限制应用程序可与每个实例一起打开的连接数。如果您的应用程序具有嵌入式连接池功能,请设置合理数量的连接。根据实例中的 CPU 可以有效并行处理的数量来确定数量。

  • 尽可能利用 PostgreSQL 的热备实例。当您的应用程序运行只读操作时,将这些请求发送到只读实例。此方法将应用程序请求分布到所有读取器节点,从而减少了写入器节点的输入/输出压力。

  • 请考虑纵向扩展数据库实例。更高容量的实例类可提供更多内存,这为 PostgreSQL 提供了一个更大的共享缓冲池来容纳页面。较大的大小还为数据库实例提供了更多的 CPU 来处理连接。当生成 DataFileRead 等待事件的操作为写入时,更多的 CPU 会特别有用。