

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 连接到 PostgreSQL 数据来源
<a name="using-postgresql-in-AMG"></a>

 您可以使用 PostgreSQL 数据来源查询和可视化 Amazon Aurora PostgreSQL 数据库中的数据。

**重要**  
*Grafana 版本 8* 更改了 Postgres、MySQL 和 Microsoft SQL Server 数据来源数据帧的底层数据结构。因此，时间序列查询结果将以宽格式返回。有关更多信息，请参阅 Grafana 数据帧文档中的[宽格式](https://grafana.com/developers/plugin-tools/introduction/data-frames#wide-format)。要使可视化效果像版本 8 之前一样，您可能需要进行一些手动迁移。Github 上记录了一个解决方案，网址为 [Postgres/MySQL/MSSQL：v8.0 中与时间序列查询和数据列排序相关的重大更改](https://github.com/grafana/grafana/issues/35534)。  
在 *Grafana 版本 9* 中，PostgreSQL 数据来源设置连接到数据库的根证书的方式与以前的版本不同。如果将工作区从版本 8 更新到版本 9，则可能需要更改连接方式。请参阅[排查与更新后的工作区相关的问题](AMG-workspace-version-update-troubleshoot.md)了解更多信息。

## 添加数据来源
<a name="postgresql-adding-the-data-source"></a>

1.  选择顶部标题中的 Grafana 图标，打开侧边菜单。

1.  在**配置**图标下的侧边菜单中，您应该可以找到**数据来源**链接。

1.  选择顶部标题中的 **\+ 添加数据来源**按钮。

1.  从**类型**下拉列表中选择 **PostgreSQL**。

### 数据来源选项
<a name="postgresql-data-source-options"></a>


|  Name  |  说明  | 
| --- | --- | 
|  Name  |  数据来源名称。您将在面板和查询中通过其名称查看数据来源。 | 
|  Default  |  默认数据来源意味着将为新面板预先选择该数据来源。 | 
|  Host  |  您的 PostgreSQL 实例的 IP address/hostname 和可选端口。请勿包含数据库名称。否则，连接到 Postgres 的连接字符串不正确，会导致错误。 | 
|  Database  |  PostgreSQL 数据库的名称。 | 
|  User  |  数据库用户的 login/username。 | 
|  Password  |  数据库用户密码  | 
|  SSL Mode  |  此选项决定是否或以什么优先级与服务器协商安全 SSL TCP/IP 连接。 | 
|  Max open  |  数据库的最大打开连接数，默认为 unlimited（Grafana v5.4\+）。 | 
|  Max idle  |  空闲连接池中的最大连接数，默认为 2（Grafana v5.4\+）。 | 
|  Max lifetime  |  连接可重复使用的最长时间（秒），默认为 14400/4 小时（Grafana v5.4\+）。 | 
|  Version  |  此选项决定了查询生成器中哪些函数可用（仅在 Grafana 5.3\+ 中可用）。 | 
|  TimescaleDB  |  TimescaleDB 是一个作为 PostgreSQL 扩展而构建的时间序列数据库。如果启用，Grafana 将在 $\_\_timeGroup 宏中使用 time\_bucket，并在查询生成器中显示 TimescaleDB 特定的聚合函数（仅在 Grafana 5.3\+ 中可用）。 | 

### 最小时间间隔
<a name="postgresql-min-time-interval"></a>

 `$_interval` `$_interval_ms` 变量的下限。建议设置以写入频率，例如，如果您的数据每分钟写入一次，则为 `1m`。此选项也可以在 overridden/configured 仪表板面板的数据源选项下方。此值的格式**必须**为数字，后跟有效的时间标识符；例如，`1m`（1 分钟）或 `30s`（30 秒）。支持以下时间标识符。


|  标识符  |  说明  | 
| --- | --- | 
|  y  |  Year  | 
|  M  |  Month  | 
|  w  |  周  | 
|  d  |  天  | 
|  h  |  小时  | 
|  m  |  分钟  | 
|  s  |  秒  | 
|  ms  |  毫秒  | 

### 数据库用户权限
<a name="postgresql-database-user-permissions-important"></a>

**重要**  
 添加数据来源时指定的数据库用户只能获得对要查询的指定数据库和表的 SELECT 权限。Grafana 不会验证查询是否安全。查询可以包含任何 SQL 语句。例如，可以运行 `DELETE FROM user;` 和 `DROP TABLE user;` 之类的语句。为了防止这种情况，强烈建议您创建具有受限权限的特定 PostgreSQL 用户。

以下示例代码显示了如何创建具有受限权限的特定 PostgreSQL 用户。

```
 CREATE USER grafanareader WITH PASSWORD 'password';
 GRANT USAGE ON SCHEMA schema TO grafanareader;
 GRANT SELECT ON schema.table TO grafanareader;
```

 确保用户没有从公有角色获得任何不需要的权限。

## 查询编辑器
<a name="postgresql-query-editor"></a>

 在图形或 Singlestat 面板编辑模式的“指标”选项卡中，您可以找到 PostgreSQL 查询编辑器。要进入编辑模式，请选择面板标题，然后选择编辑。

 在面板编辑模式下，查询编辑器有一个**生成式 SQL** 链接，并在查询运行后显示。选择之后，将会展开并显示运行的原始插值 SQL 字符串。

### 选择表、时间列和指标列（FROM）
<a name="postgresql-select-table-time-column-and-metric-column-from"></a>

 当您首次进入编辑模式或添加新查询时，Grafana 将尝试在查询生成器中预填充第一个包含时间戳列和数字列的表。

 在 FROM 字段中，Grafana 会建议使用数据库用户 `search_path` 中的表。要选择 `search_path` 中没有的表或视图，可以手动输入完全限定名称（schema.table），例如 `public.metrics`。

 “时间”列字段引用保存时间值的列的名称。为指标列字段选择值是可选项。如果选择一个值，则“指标”列字段将用作序列名称。

 指标列建议仅包含文本数据类型（char、varchar、text）的列。要将具有不同数据类型的列作为指标列，可以通过强制转换 `ip::text` 输入列名称。您也可以在指标列字段中输入任意 SQL 表达式，这些表达式的计算结果为文本数据类型，例如 `hostname || ' ' || container_name`。

### 列、窗口和聚合函数（SELECT）
<a name="columns-window-and-aggregation-functions-select"></a>

 在 `SELECT` 行中，您可以指定要使用的列和函数。在列字段中，您可以编写任意表达式来代替列名称，例如 `column1 * column2 / column3`。

 查询编辑器中的可用函数取决于您在配置数据来源时选择的 PostgreSQL 版本。如果使用聚合函数，则必须对结果集分组。如果添加聚合函数，编辑器将自动添加 `GROUP BY time`。

编辑器尝试简化和统一这部分查询。

选择加号按钮并从菜单中选择**列**，即可添加更多值列。多个值列将在图形面板中绘制为单独的序列。

### 筛选数据（WHERE）
<a name="postgresql-filter-data-where"></a>

 要添加筛选条件，请选择 `WHERE` 条件右侧的加号图标。您可以选择筛选条件，然后选择**移除**来移除筛选条件。当前所选时间范围的筛选条件会自动添加到新查询中。

### 分组依据
<a name="postgresql-group-by"></a>

 要按时间或任何其他列分组，请选择 GROUP BY 行末尾的加号图标。建议下拉列表将仅显示当前所选表的文本列，但可以手动输入任何列。您可以在项目上进行选择，然后选择**移除**来移除组。

 如果添加任何分组，则所有选定的列都必须应用聚合函数。添加分组时，查询生成器会自动向所有没有聚合函数的列添加聚合函数。

#### 填充缺失值
<a name="postgresql-gap-filling"></a>

 按时间分组时，Amazon Managed Grafana 可以填充缺失值。time 函数接受两个参数。第一个参数是要作为分组依据的时间窗口，第二个参数是您希望 Grafana 填充缺失项目的值。

### 文本编辑器模式（原始）
<a name="postgresql-text-editor-mode-raw"></a>

 选择汉堡包图标并选择**切换编辑器模式**或在查询下方选择**编辑 SQL**，即可切换到原始查询编辑器模式。

**注意**  
 如果使用原始查询编辑器，请确保您的查询至少具有 `ORDER BY time` 和返回时间范围的筛选条件。

## 宏
<a name="postgresql-macros"></a>

 可在查询中使用宏来简化语法，并允许使用动态部分。


|  宏示例  |  说明  | 
| --- | --- | 
|  $\_\_time(dateColumn)  |  将替换为一个表达式，以转换为 UNIX 时间戳，并将列重命名为 time\_sec。例如，UNIX\_TIMESTAMP(dateColumn) as time\_sec。 | 
|  $\_\_timeEpoch(dateColumn)  |  将替换为一个表达式，以转换为 UNIX 时间戳，并将列重命名为 time\_sec。例如，UNIX\_TIMESTAMP(dateColumn) as time\_sec。 | 
|  $\_\_timeFilter(dateColumn)  |  将替换为使用指定列名的时间范围筛选条件。例如，dateColumn BETWEEN FROM\_UNIXTIME(1494410783) AND FROM\_UNIXTIME(1494410983)。 | 
|  $\_\_timeFrom()  |  将替换为当前活动时间选择的开始时间。例如，FROM\_UNIXTIME(1494410783)。 | 
|  $\_\_timeTo()  |  将替换为当前活动时间选择的结束时间。例如，FROM\_UNIXTIME(1494410983)。 | 
|  $\_\_timeGroup(dateColumn,'5m')  |  将替换为 GROUP BY 子句中可用的表达式。例如，cast(cast(UNIX\_TIMESTAMP(dateColumn)/(300) as signed)300 as signed),\*  | 
|  $\_\_timeGroup(dateColumn,'5m', 0)  |  与前一行相同，但带有填充参数，序列中缺失的点将由 Grafana 添加，0 将用作值。 | 
|  $\_\_timeGroup(dateColumn,'5m', NULL)  |  与上面相同，但 NULL 将用作缺失点的值。 | 
|  $\_\_timeGroup(dateColumn,'5m', previous)  |  与上面相同，但如果未看到任何值，则该序列中的前一个值将用作填充值，但使用 NULL（仅适用于 Grafana 5.3\+）。 | 
|  $\_\_timeGroupAlias(dateColumn,'5m')  |  与 $\_\_timeGroup 相同，但增加了列别名  | 
|  $\_\_unixEpochFilter(dateColumn) |  将使用指定列名替换为时间范围筛选条件，其中时间表示为 Unix 时间戳 例如，\*dateColumn > 1494410783 AND dateColumn < 1494497183\* | 
| $\_\_unixEpochFrom()`  | \| 将替换为当前活动时间选择的开始，作为 Unix 时间戳。例如，\*1494410783\* | 
| $\_\_unixEpochTo() | 将替换为当前活动时间选择的结束时间，作为 Unix 时间戳。例如，\*1494497183\* | 
| $\_\_unixEpochNanoFilter(dateColumn) | 将使用指定列名替换为时间范围筛选条件，其中时间表示为纳秒时间戳。例如，\*dateColumn > 1494410783152415214 AND dateColumn < 1494497183142514872\* | 
| $\_\_unixEpochNanoFrom() | 将替换为当前活动时间选择的开始时间，作为纳秒时间戳。例如，\*1494410783152415214\* | 
| $\_\_unixEpochNanoTo() | 将替换为当前活动时间选择的结束时间，作为纳秒时间戳。例如，\*1494497183142514872\* | 
| $\_\_unixEpochGroup(dateColumn,"5m", [fillmode]) | 与 $\_\_timeGroup 相同，但时间存储为 Unix 时间戳。 | 

## 表查询
<a name="postgresql-table-queries"></a>

 如果查询选项设置为**格式化为表**，则基本上可以执行任何类型的 SQL 查询。表面板将自动显示查询返回的任何列和行的结果。

 您可以使用常规 `as` SQL 列选择语法来控制表面板列的名称。

## 时间序列查询
<a name="postgresql-time-series-queries"></a>

 如果将**格式化为**设置为 `Time series`，例如在图形面板中使用，查询必须有一个名为 `time` 的列，该列返回 SQL 日期时间或任何表示 Unix 纪元的数字数据类型。除 `time` 和 `metric` 之外的任何列都被视为值列。您可以返回一个名为 `metric` 的列，该列用作值列的指标名称。如果返回多个值列和一个名为的 `metric` 列，则此列将用作序列名称的前缀。

 时间序列查询的结果集必须按时间排序。

 以下示例代码显示了一个 `metric` 列。

```
SELECT
  $__timeGroup("time_date_time",'5m'),
  min("value_double"),
  'min' as metric
FROM test_data
WHERE $__timeFilter("time_date_time")
GROUP BY time
ORDER BY time
```

 以下代码示例显示了如何使用 $\_\_timeGroup 宏中的填充参数将空值转换为零。

```
SELECT
  $__timeGroup("createdAt",'5m',0),
  sum(value) as value,
  measurement
FROM test_data
WHERE
  $__timeFilter("createdAt")
GROUP BY time, measurement
ORDER BY time
```

 以下示例代码显示了多个列。

```
SELECT
  $__timeGroup("time_date_time",'5m'),
  min("value_double") as "min_value",
  max("value_double") as "max_value"
FROM test_data
WHERE $__timeFilter("time_date_time")
GROUP BY time
ORDER BY time
```

## 模板化
<a name="postgresql-templating"></a>

 您可以在指标查询中使用变量来代替服务器、应用程序和传感器名称等硬编码。变量显示为控制面板顶部的下拉选择框。您可以使用这些下拉框来更改控制面板中显示的数据。

 有关模板化和模板变量的更多信息，请参阅 [模板](templates-and-variables.md#templates)。

### 查询变量
<a name="postgresql-query-variable"></a>

 如果添加 `Query` 类型的模板变量，则可以编写一个 PostgreSQL 查询，该查询可以返回测量名称、键名或键值等显示为下拉选择框的内容。

 例如，如果在模板变量 *Query* 设置中指定了这样的查询，则会有一个变量，其中包含表中 `hostname` 列的所有值的。

```
SELECT hostname FROM host
```

 查询可以返回多列，Grafana 会自动根据这些列创建一个列表。例如，以下查询将返回一个列表，其中包含来自 `hostname` 和 `hostname2` 的值。

```
SELECT host.hostname, other_host.hostname2 FROM host JOIN other_host ON host.city = other_host.city
```

 要在查询中使用依赖于时间范围的宏（如 `$__timeFilter(column)`），必须将模板变量的刷新模式设置为*时间范围更改时*。

```
SELECT event_name FROM event_log WHERE $__timeFilter(time_column)
```

 另一种选择是可以创建 key/value 变量的查询。该查询应返回名为 `__text` 和 `__value` 的两列。`__text` 列值应该是唯一的（如果不是唯一的，则使用第一个值）。下拉列表中的选项包含文本和值，允许将友好名称作为文本，将 id 作为值。以 `hostname` 作为文本，以 `id` 作为值的示例查询：

```
SELECT hostname AS __text, id AS __value FROM host
```

 您还可以创建嵌套变量。使用名为 `region` 的变量，可以让主机变量仅显示当前所选区域的主机。以下代码示例显示了这样的查询（如果 `region` 是多值变量，则使用 `IN` 比较运算符而不是 `=` 与多个值匹配）。

```
SELECT hostname FROM host  WHERE region IN($region)
```

#### 使用 `__searchFilter` 筛选查询变量结果
<a name="postgresql-using-__searchfilter-to-filter-results-in-query-variable"></a>

 在查询字段中使用 `__searchFilter`，根据用户在下拉选择框中输入的内容筛选查询结果。当用户未输入任何内容时，`__searchFilter` 的默认值为 `%`。

**注意**  
 请务必用引号将 `__searchFilter` 表达式括起来，因为 Grafana 不会为您执行此操作。

 以下示例显示了当用户在下拉选择框中键入时，如何使用 `__searchFilter` 作为查询字段的一部分来启用 `hostname` 搜索。

```
SELECT hostname FROM my_host  WHERE hostname LIKE '$__searchFilter'
```

### 在查询中使用变量
<a name="postgresql-using-variables-in-queries"></a>

 仅当模板变量是 `multi-value` 时，才会引用模板变量值。

 如果该变量是多值变量，则使用 `IN` 比较运算符而不是 `=` 与多个值匹配。

 共有两种语法：

 `$<varname>` 名为 `hostname` 的模板变量的示例：

```
SELECT
  atimestamp as time,
  aint as value
FROM table
WHERE $__timeFilter(atimestamp) and hostname in($hostname)
ORDER BY atimestamp ASC
```

 `[[varname]]` 名为 `hostname` 的模板变量的示例：

```
SELECT
  atimestamp as time,
  aint as value
FROM table
WHERE $__timeFilter(atimestamp) and hostname in([[hostname]])
ORDER BY atimestamp ASC
```

#### 关闭多值变量的引用
<a name="postgresql-disabling-quoting-for-multi-value-variables"></a>

 Amazon Managed Grafana 会自动为多值变量创建带引号、以逗号分隔的字符串。例如，如果选择 `server01` 和 `server02`，则其格式为：`'server01', 'server02'`。要关闭引用，请对变量使用 csv 格式选项。

 `${servers:csv}` 

 有关变量格式选项的更多信息，请参阅 [模板和变量](templates-and-variables.md)。

## Annotations
<a name="postgresql-annotations"></a>

 使用注释在图形上叠加丰富的事件信息。您可以通过控制面板菜单/注释视图添加注释查询。有关更多信息，请参阅 [Annotations](dashboard-annotations.md)。

 以下示例代码演示了一个查询，该查询使用具有纪元值的 time 列。

```
SELECT
  epoch_time as time,
  metric1 as text,
  concat_ws(', ', metric1::text, metric2::text) as tags
FROM
  public.test_data
WHERE
  $__unixEpochFilter(epoch_time)
```

 以下示例代码演示了一个区域查询，该查询使用具有纪元值的 time 和 timeend 列。

**注意**  
 仅在 Grafana v6.6\+ 中可用。

```
SELECT
  epoch_time as time,
  epoch_time_end as timeend,
  metric1 as text,
  concat_ws(', ', metric1::text, metric2::text) as tags
FROM
  public.test_data
WHERE
  $__unixEpochFilter(epoch_time)
```

 以下示例代码显示了使用原生 SQL date/time 数据类型的时间列的查询。

```
SELECT
  native_date_time as time,
  metric1 as text,
  concat_ws(', ', metric1::text, metric2::text) as tags
FROM
  public.test_data
WHERE
  $__timeFilter(native_date_time)
```


|  Name  |  说明  | 
| --- | --- | 
|  time  |  date/time 字段的名称。可以是具有本机 SQL date/time 数据类型或纪元值的列。 | 
|  timeend  |  结束 date/time 字段的可选名称。可能是具有原生 SQL date/time 数据类型或时代值的列（Grafana v6.6\+）。 | 
|  text  |  事件描述字段。 | 
|  tags  |  用于事件标签的可选字段名称，显示为以逗号分隔的字符串。 | 

## 警报
<a name="postgresql-alerting"></a>

 时间序列查询应在警报条件下工作。警报规则条件尚不支持表格式查询。