我的应用程序将接收用户提交的选择查询,但不是执行它并获得完整的结果集,在这个阶段,它只需要列名和&类型。
用户将是数据分析师,因此我希望提交大量冗长的查询。随着数据量的增长,提交的查询将在应用程序中保留并经常评估(基于触发器和crons的混合)。
客户端应用程序是用python& sqlalchemy-core与数据库进行交互。
目前我在查询结尾追加LIMIT 0
以获取结果元数据。到目前为止,这给了我可接受的结果
示例:
查询待检查:
SELECT * FROM users
探究查询
SELECT * FROM users LIMIT 0
EXPLAIN ANALYZE
会返回以下结果:
Limit (cost=0.00..0.11 rows=1 width=646) (actual time=0.001..0.001 rows=0 loops=1)
-> Seq Scan on users (cost=0.00..22457.28 rows=207728 width=646) (never executed)
Planning time: 0.067 ms
Execution time: 0.025 ms
请注意Seq Scan on users
有一个注释(never executed)
。
接下来,我在一个更复杂的查询上尝试LIMIT 0
,结果如下:
EXPLAIN ANALYZE
WITH blah AS (
SELECT *
FROM users
JOIN reservation
ON reservation.user_id = users.id
)
SELECT * FROM blah
LIMIT 0
-- result:
Limit (cost=482925.94..482925.96 rows=1 width=1955) (actual time=0.001..0.001 rows=0 loops=1)
CTE blah
-> Hash Join (cost=42094.88..482925.94 rows=1563750 width=1418) (never executed)
Hash Cond: (reservation.user_id = users.id)
-> Seq Scan on reservation (cost=0.00..96868.50 rows=1563750 width=772) (never executed)
-> Hash (cost=22457.28..22457.28 rows=207728 width=646) (never executed)
-> Seq Scan on users (cost=0.00..22457.28 rows=207728 width=646) (never executed)
-> CTE Scan on blah (cost=0.00..31275.00 rows=1563750 width=1955) (never executed)
Planning time: 8.284 ms
Execution time: 0.113 ms
同样,所产生的唯一成本是计划时间和时间。更短的执行时间。
问题:
假设总时间的上限是规划时间的两倍是否安全?
在Postgresql中,我认为CTE一直都是优化围栏。但是,对于LIMIT 0
,CTE似乎没有实现(never executed)
。这是我可以依赖的行为(9.5 +)
是否有更简单/更有效的方法来获取选择查询的元数据? 如果我可以假设上述第1点,那么这不是一个非常重要的问题
传闻,您在SELECT查询中观察到的最大规划时间是什么?
我很确定即使数据量在基础表中增长,我也可以假设同一查询的计划时间相似。是否存在不适用的情况?
答案 0 :(得分:1)
我认为在大多数情况下执行时间大致保持不变,但数据修改CTE的情况除外(见下文)。
如果CTE永远不会被使用,则不会执行。此规则的例外情况是CTE中是否存在数据修改语句;在这种情况下,CTE始终执行。
我不认为PL / Python有更好的方法。如果你编写一个C函数,你可以准备语句,然后得到它的结果列,但它也可能是非平凡的。
没有很酷的故事要分享......
计划时间与表格的大小无关。