我的应用程序将接收用户提交的选择查询,但不是执行它并获得完整的结果集,在这个阶段,它只需要列名称&类型.
用户将是数据分析师,因此我希望提交大量冗长的查询.随着数据量的增长,提交的查询将在应用程序中保留并经常评估(基于触发器和触发器的混合).
客户端应用程序是用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有一个注释(从未执行过).
接下来,我在一个更复杂的查询上尝试了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似乎没有实现(从未执行过).这是我可以依赖的行为(9.5)
>是否有更简单/更有效的方法来获取选择查询的元数据?如果我可以假设上面的第1点,那么这不是一个非常重要的问题
>有趣的是,您在SELECT查询中观察到的最大规划时间是多少?
>我很确定即使数据量在基础表中增长,我也可以假设同一查询的计划时间相似.是否存在不适用的情况?
最佳答案 >我认为在大多数情况下执行时间将是恒定的,除了数据修改CTE的明显例外(见下文).
>如果CTE永远不会被使用,则不会执行.此规则的例外情况是CTE中是否存在数据修改语句;在这种情况下,CTE始终执行.
>我不认为PL / Python有更好的方法.如果你编写一个C函数,你可以准备语句,然后得到它的结果列,但它也可能是非平凡的.
>没有很酷的故事要分享……
>计划时间与表的大小无关.