- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
使用 PostgreSQL 11.1,我有一个参数类型为 text
的函数。它在 CASE WHEN
结构中大量使用,通常是嵌套的。
最近遇到一个很奇怪的现象:假设在我的函数中我有类似 CASE WHEN $1 = 'foo') THEN id ...
的东西,我现在执行带有参数值 foo
的函数。一切都按预期工作,但速度很慢。
如果在函数内部,我将 $1 = 'foo'
替换为 'foo' = 'foo'
它应该与传递值 具有相同的效果>foo
代表 $1
。结果确实是一样的。它只是更快!
在我的真实示例中,差异是 400 毫秒到 25 秒!
我创建了两个类似于该现象的函数(见下文)。那里的代码是高度重复的以获得一些意义。在我的机器上,不带参数的版本需要 6 秒,而带参数的版本大约需要 16 秒。 (我已将执行包装在 PLV8 DO
语句中,这样结果不会使客户端膨胀)
所以,我的问题是:怎么会这样?为什么将参数值与字符串进行比较比比较两个字符串花费的时间要多得多?我无法理解。第二个问题:我可以在这里做些什么来提高性能吗?我需要那个参数。
编辑:EXPLAIN ANALYZE 的结果
在函数调用前添加 EXPLAIN ANALYZE
会得到这些结果:
没有参数
Result (cost=0.00..0.26 rows=1 width=32) (actual time=5429.874..5432.217 rows=1 loops=1)
Planning Time: 0.615 ms
Execution Time: 5435.469 ms
带参数
Result (cost=0.00..0.26 rows=1 width=32) (actual time=15585.637..15588.569 rows=1 loops=1)
Planning Time: 0.213 ms
Execution Time: 15591.640 ms
编辑 2:自动记录的结果
没有参数
Aggregate (cost=47.52..47.53 rows=1 width=32) (actual time=6248.177..6248.178 rows=1 loops=1)
CTE myData
-> ProjectSet (cost=0.00..5.02 rows=1000 width=4) (actual time=0.003..689.085 rows=10000000 loops=1)
-> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.000..0.001 rows=1 loops=1)
CTE nestedCases
-> CTE Scan on "myData" (cost=0.00..20.00 rows=1000 width=40) (actual time=0.004..2692.660 rows=10000000 loops=1)
-> CTE Scan on "nestedCases" (cost=0.00..20.00 rows=1000 width=4) (actual time=0.005..5434.799 rows=10000000 loops=1)
带参数
Aggregate (cost=197.52..197.53 rows=1 width=32) (actual time=16568.033..16568.033 rows=1 loops=1)
CTE myData
-> ProjectSet (cost=0.00..5.02 rows=1000 width=4) (actual time=0.002..728.866 rows=10000000 loops=1)
-> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.000..0.001 rows=1 loops=1)
CTE nestedCases
-> CTE Scan on "myData" (cost=0.00..170.00 rows=1000 width=40) (actual time=0.010..12851.991 rows=10000000 loops=1)
-> CTE Scan on "nestedCases" (cost=0.00..20.00 rows=1000 width=4) (actual time=0.012..15686.157 rows=10000000 loops=1)
附录:函数完整代码
代码基本上是胡说八道:它生成一个巨大的系列,并使用嵌套的 CASE WHEN
获取值 10 次。
A) 带参数的函数
CREATE OR REPLACE FUNCTION public.function_with_param(role text)
RETURNS integer[]
LANGUAGE sql
STABLE
AS $function$
WITH "myData" AS (
SELECT generate_series(1,10000000) AS id
),
"nestedCases" AS (
SELECT
CASE WHEN ($1 = 'bar') THEN 0
WHEN ($1 = 'foo') THEN
CASE WHEN ($1 = 'huhu') AND id = 1 THEN id + 452
WHEN ($1 = 'foo') THEN id
END
END
AS id,
CASE WHEN ($1 = 'bar') THEN 0
WHEN ($1 = 'foo') THEN
CASE WHEN ($1 = 'huhu') AND id = 1 THEN id + 452
WHEN ($1 = 'foo') THEN id
END
END
AS id2,
CASE WHEN ($1 = 'bar') THEN 0
WHEN ($1 = 'foo') THEN
CASE WHEN ($1 = 'huhu') AND id = 1 THEN id + 452
WHEN ($1 = 'foo') THEN id
END
END
AS id3,
CASE WHEN ($1 = 'bar') THEN 0
WHEN ($1 = 'foo') THEN
CASE WHEN ($1 = 'huhu') AND id = 1 THEN id + 452
WHEN ($1 = 'foo') THEN id
END
END
AS id4,
CASE WHEN ($1 = 'bar') THEN 0
WHEN ($1 = 'foo') THEN
CASE WHEN ($1 = 'huhu') AND id = 1 THEN id + 452
WHEN ($1 = 'foo') THEN id
END
END
AS id5,
CASE WHEN ($1 = 'bar') THEN 0
WHEN ($1 = 'foo') THEN
CASE WHEN ($1 = 'huhu') AND id = 1 THEN id + 452
WHEN ($1 = 'foo') THEN id
END
END
AS id6,
CASE WHEN ($1 = 'bar') THEN 0
WHEN ($1 = 'foo') THEN
CASE WHEN ($1 = 'huhu') AND id = 1 THEN id + 452
WHEN ($1 = 'foo') THEN id
END
END
AS id7,
CASE WHEN ($1 = 'bar') THEN 0
WHEN ($1 = 'foo') THEN
CASE WHEN ($1 = 'huhu') AND id = 1 THEN id + 452
WHEN ($1 = 'foo') THEN id
END
END
AS id8,
CASE WHEN ($1 = 'bar') THEN 0
WHEN ($1 = 'foo') THEN
CASE WHEN ($1 = 'huhu') AND id = 1 THEN id + 452
WHEN ($1 = 'foo') THEN id
END
END
AS id9,
CASE WHEN ($1 = 'bar') THEN 0
WHEN ($1 = 'foo') THEN
CASE WHEN ($1 = 'huhu') AND id = 1 THEN id + 452
WHEN ($1 = 'foo') THEN id
END
END
AS id10
FROM "myData"
)
SELECT array_agg(id) FROM "nestedCases"
$function$
B) 带有out 参数的函数。我已将 $1
替换为 /*P*/'foo'/*P*/
以便您可以看到我在这里做了什么
CREATE OR REPLACE FUNCTION public.function_without_param()
RETURNS integer[]
LANGUAGE sql
STABLE
AS $function$
WITH "myData" AS (
SELECT generate_series(1,10000000) AS id
),
"nestedCases" AS (
SELECT
CASE WHEN (/*P*/'foo'/*P*/ = 'bar') THEN 0
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN
CASE WHEN (/*P*/'foo'/*P*/ = 'huhu') AND id = 1 THEN id + 452
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN id
END
END
AS id,
CASE WHEN (/*P*/'foo'/*P*/ = 'bar') THEN 0
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN
CASE WHEN (/*P*/'foo'/*P*/ = 'huhu') AND id = 1 THEN id + 452
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN id
END
END
AS id2,
CASE WHEN (/*P*/'foo'/*P*/ = 'bar') THEN 0
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN
CASE WHEN (/*P*/'foo'/*P*/ = 'huhu') AND id = 1 THEN id + 452
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN id
END
END
AS id3,
CASE WHEN (/*P*/'foo'/*P*/ = 'bar') THEN 0
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN
CASE WHEN (/*P*/'foo'/*P*/ = 'huhu') AND id = 1 THEN id + 452
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN id
END
END
AS id4,
CASE WHEN (/*P*/'foo'/*P*/ = 'bar') THEN 0
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN
CASE WHEN (/*P*/'foo'/*P*/ = 'huhu') AND id = 1 THEN id + 452
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN id
END
END
AS id5,
CASE WHEN (/*P*/'foo'/*P*/ = 'bar') THEN 0
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN
CASE WHEN (/*P*/'foo'/*P*/ = 'huhu') AND id = 1 THEN id + 452
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN id
END
END
AS id6,
CASE WHEN (/*P*/'foo'/*P*/ = 'bar') THEN 0
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN
CASE WHEN (/*P*/'foo'/*P*/ = 'huhu') AND id = 1 THEN id + 452
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN id
END
END
AS id7,
CASE WHEN (/*P*/'foo'/*P*/ = 'bar') THEN 0
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN
CASE WHEN (/*P*/'foo'/*P*/ = 'huhu') AND id = 1 THEN id + 452
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN id
END
END
AS id8,
CASE WHEN (/*P*/'foo'/*P*/ = 'bar') THEN 0
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN
CASE WHEN (/*P*/'foo'/*P*/ = 'huhu') AND id = 1 THEN id + 452
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN id
END
END
AS id9,
CASE WHEN (/*P*/'foo'/*P*/ = 'bar') THEN 0
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN
CASE WHEN (/*P*/'foo'/*P*/ = 'huhu') AND id = 1 THEN id + 452
WHEN (/*P*/'foo'/*P*/ = 'foo') THEN id
END
END
AS id10
FROM "myData"
)
SELECT array_agg(id) FROM "nestedCases"
$function$
最佳答案
如果您使用硬编码常量,则可以在计划时间内对所有表达式求值。由于查询计划缓存在 PL/pgSQL 函数中,因此只发生一次。
如果您使用参数,则每次调用函数时都必须在运行时计算表达式。
关于sql - PostgreSQL:在嵌套 CASE WHEN 中使用文本参数会显着降低查询速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53881342/
简而言之:我想从可变参数模板参数中提取各种选项,但不仅通过标签而且通过那些参数的索引,这些参数是未知的 标签。我喜欢 boost 中的方法(例如 heap 或 lockfree 策略),但想让它与 S
我可以对单元格中的 excel IF 语句提供一些帮助吗? 它在做什么? 对“BaselineAmount”进行了哪些评估? =IF(BaselineAmount, (Variance/Baselin
我正在使用以下方法: public async Task Save(Foo foo,out int param) { ....... MySqlParameter prmparamID
我正在使用 CodeGear RAD Studio IDE。 为了使用命令行参数测试我的应用程序,我多次使用了“运行 -> 参数”菜单中的“参数”字段。 但是每次我给它提供一个新值时,它都无法从“下拉
我已经为信用卡类编写了一些代码,粘贴在下面。我有一个接受上述变量的构造函数,并且正在研究一些方法将这些变量格式化为字符串,以便最终输出将类似于 号码:1234 5678 9012 3456 截止日期:
MySql IN 参数 - 在存储过程中使用时,VarChar IN 参数 val 是否需要单引号? 我已经像平常一样创建了经典 ASP 代码,但我没有更新该列。 我需要引用 VarChar 参数吗?
给出了下面的开始,但似乎不知道如何完成它。本质上,如果我调用 myTest([one, Two, Three], 2); 它应该返回元素 third。必须使用for循环来找到我的解决方案。 funct
将 1113355579999 作为参数传递时,该值在函数内部变为 959050335。 调用(main.c): printf("%d\n", FindCommonDigit(111335557999
这个问题在这里已经有了答案: Is Java "pass-by-reference" or "pass-by-value"? (92 个回答) 关闭9年前。 public class StackOve
我真的很困惑,当像 1 == scanf("%lg", &entry) 交换为 scanf("%lg", &entry) == 1 没有区别。我的实验书上说的是前者,而我觉得后者是可以理解的。 1 =
我正在尝试使用调用 SetupDiGetDeviceRegistryProperty 的函数使用德尔福 7。该调用来自示例函数 SetupEnumAvailableComPorts .它看起来像这样:
我需要在现有项目上实现一些事件的显示。我无法更改数据库结构。 在我的 Controller 中,我(从 ajax 请求)传递了一个时间戳,并且我需要显示之前的 8 个事件。因此,如果时间戳是(转换后)
rails 新手。按照多态关联的教程,我遇到了这个以在create 和destroy 中设置@client。 @client = Client.find(params[:client_id] || p
通过将 VM 参数设置为 -Xmx1024m,我能够通过 Eclipse 运行 Java 程序-Xms256M。现在我想通过 Windows 中的 .bat 文件运行相同的 Java 程序 (jar)
我有一个 Delphi DLL,它在被 Delphi 应用程序调用时工作并导出声明为的方法: Procedure ProduceOutput(request,inputs:widestring; va
浏览完文档和示例后,我还没有弄清楚 schema.yaml 文件中的参数到底用在哪里。 在此处使用 AWS 代码示例:https://github.com/aws-samples/aws-proton
程序参数: procedure get_user_profile ( i_attuid in ras_user.attuid%type, i_data_group in data_g
我有一个字符串作为参数传递给我的存储过程。 dim AgentString as String = " 'test1', 'test2', 'test3' " 我想在 IN 中使用该参数声明。 AND
这个问题已经有答案了: When should I use "this" in a class? (17 个回答) 已关闭 6 年前。 我运行了一些java代码,我看到了一些我不太明白的东西。为什么下
我输入 scroll(0,10,200,10);但是当它运行时,它会传递字符串“xxpos”或“yypos”,我确实在没有撇号的情况下尝试过,但它就是行不通。 scroll = function(xp
我是一名优秀的程序员,十分优秀!