Postgres Select 执行顺序不正确
Postgres Select execution order incorrect
以下查询在 Postgres 9.4.5 中不起作用。
SELECT * FROM (
SELECT M.NAME, M.VALUE AS V
FROM METRICS AS M, METRICATTRIBUTES AS A
WHERE M.NAME=A.NAME AND A.ISSTRING='FALSE'
) AS S1
WHERE CAST(S1.V AS NUMERIC)<0
我收到如下错误:
invalid input syntax for type numeric: "astringvalue"
继续阅读以了解为什么我将查询设置得如此复杂。
METRICS 是一个 table 的度量值对。这些值存储为字符串,并且 VALUE 字段的某些值实际上是字符串。 METRICATTRIBUTES table 标识那些可能具有字符串值的指标名称。我根据对 METRICS table 的分析填充了 METRICATTRIBUTES table。
为了检查,我 运行...
SELECT * FROM (
SELECT M.NAME, M.VALUE AS V
FROM METRICS AS M, METRICATTRIBUTES AS A
WHERE M.NAME=A.NAME AND A.ISSTRING='FALSE'
) AS S1
WHERE S1.V LIKE 'a%'
这 returns 没有值(如我所料)。错误似乎在执行计划中。看起来像这样(抱歉,我不得不粗指这个)
1 -> HAS JOIN
2 HASH COND: ((M.NAME::TEXT=(A.NAME)::TEXT))
3 SEQ SCAN ON METRICS M
4 FILTER: ((VALUE)::NUMERIC<0::NUMERIC)
5 -> HASH
6 -> Seq Scan on METRICATTRIBUTES A
7 Filter: (NOT ISSTRING)
我不是这方面的专家(只有 1 周的 Postgres 经验),但看起来 Postgres 正在尝试在应用连接条件(第 2 行)之前应用强制转换(第 4 行)。通过这样做,它将尝试将转换应用于无效的字符串值,这正是我试图避免的!
用显式连接写这个没有任何区别。将它写成单个 select 语句是我的第一次尝试,没想到会出现这种类型的问题。那也没有用。
有什么想法吗?
正如您从您的计划中看到的,table METRICS
正在被完整扫描 (Seq Scan
) 并根据您的条件进行过滤:CAST(S1.V AS NUMERIC)<0
—join does not完全限制了范围。
显然,您有一些行在 METRICS.VALUE
中包含非数字数据。
检查您的 table 是否有这样的行:
SELECT * FROM METRICS
WHERE NOT VALUE ~ '^([0-9].,e)*$'
请注意,很难用正则表达式捕获所有可能的组合,因此请查看此相关问题:isnumeric() with PostgreSQL
列名称 VALUE
不好,因为这个词 is a reserved one.
编辑: 如果你绝对确定,加入的 tables 会产生想要的 VALUE
-s,而不是你可以使用 CTEs, 在 PostgreSQL 中具有优化栅栏功能:
WITH S1 AS (
SELECT M.NAME, M.VALUE AS V
FROM METRICS AS M
JOIN METRICATTRIBUTES AS A USING (NAME)
WHERE A.ISSTRING='FALSE'
)
SELECT *
FROM S1
WHERE CAST(S1.V AS NUMERIC)<0;
以下查询在 Postgres 9.4.5 中不起作用。
SELECT * FROM (
SELECT M.NAME, M.VALUE AS V
FROM METRICS AS M, METRICATTRIBUTES AS A
WHERE M.NAME=A.NAME AND A.ISSTRING='FALSE'
) AS S1
WHERE CAST(S1.V AS NUMERIC)<0
我收到如下错误:
invalid input syntax for type numeric: "astringvalue"
继续阅读以了解为什么我将查询设置得如此复杂。
METRICS 是一个 table 的度量值对。这些值存储为字符串,并且 VALUE 字段的某些值实际上是字符串。 METRICATTRIBUTES table 标识那些可能具有字符串值的指标名称。我根据对 METRICS table 的分析填充了 METRICATTRIBUTES table。
为了检查,我 运行...
SELECT * FROM (
SELECT M.NAME, M.VALUE AS V
FROM METRICS AS M, METRICATTRIBUTES AS A
WHERE M.NAME=A.NAME AND A.ISSTRING='FALSE'
) AS S1
WHERE S1.V LIKE 'a%'
这 returns 没有值(如我所料)。错误似乎在执行计划中。看起来像这样(抱歉,我不得不粗指这个)
1 -> HAS JOIN
2 HASH COND: ((M.NAME::TEXT=(A.NAME)::TEXT))
3 SEQ SCAN ON METRICS M
4 FILTER: ((VALUE)::NUMERIC<0::NUMERIC)
5 -> HASH
6 -> Seq Scan on METRICATTRIBUTES A
7 Filter: (NOT ISSTRING)
我不是这方面的专家(只有 1 周的 Postgres 经验),但看起来 Postgres 正在尝试在应用连接条件(第 2 行)之前应用强制转换(第 4 行)。通过这样做,它将尝试将转换应用于无效的字符串值,这正是我试图避免的!
用显式连接写这个没有任何区别。将它写成单个 select 语句是我的第一次尝试,没想到会出现这种类型的问题。那也没有用。
有什么想法吗?
正如您从您的计划中看到的,table METRICS
正在被完整扫描 (Seq Scan
) 并根据您的条件进行过滤:CAST(S1.V AS NUMERIC)<0
—join does not完全限制了范围。
显然,您有一些行在 METRICS.VALUE
中包含非数字数据。
检查您的 table 是否有这样的行:
SELECT * FROM METRICS
WHERE NOT VALUE ~ '^([0-9].,e)*$'
请注意,很难用正则表达式捕获所有可能的组合,因此请查看此相关问题:isnumeric() with PostgreSQL
列名称 VALUE
不好,因为这个词 is a reserved one.
编辑: 如果你绝对确定,加入的 tables 会产生想要的 VALUE
-s,而不是你可以使用 CTEs, 在 PostgreSQL 中具有优化栅栏功能:
WITH S1 AS (
SELECT M.NAME, M.VALUE AS V
FROM METRICS AS M
JOIN METRICATTRIBUTES AS A USING (NAME)
WHERE A.ISSTRING='FALSE'
)
SELECT *
FROM S1
WHERE CAST(S1.V AS NUMERIC)<0;