我提出这样的问题
EXPLAIN (ANALYZE ,BUFFERS )
SELECT COUNT(id) q, day
FROM my_table
WHERE role_id && ARRAY[15, 17]
GROUP BY "day"
ORDER BY "day" DESC;
Run Code Online (Sandbox Code Playgroud)
Postgres用这个回复我:
规划时间:0.286 ms
执行时间:127.233 ms
为什么是这样 ?我认为差异太大了
我没有看到这个实现中的错误:
CREATE FUNCTION foo(anyelement) RETURNS SETOF int AS $f$
SELECT id FROM unnest(array[1,2,3]) t(id)
WHERE CASE WHEN (pg_typeof($1)::text)='integer' THEN $1::int>2 ELSE true END
$f$ LANGUAGE SQL IMMUTABLE;
SELECT * FROM foo(123); -- OK!
SELECT * FROM foo('test'::text); -- BUG
Run Code Online (Sandbox Code Playgroud)
这是某种 PostgreSQL 错误还是对anyelement
数据类型的未记录限制?
有趣的是:当孤立时,该CASE
子句可以正常工作:
CREATE FUNCTION bar(anyelement) RETURNS boolean AS $f$
SELECT CASE WHEN (pg_typeof($1)::text)='integer' THEN $1::int>2;
$f$ LANGUAGE SQL IMMUTABLE;
SELECT bar('test'::text), bar(123), bar(1); -- works fine!
Run Code Online (Sandbox Code Playgroud) 我有两个查询执行相同的操作。1
SELECT *
FROM "Products_product"
WHERE ("Products_product"."id" IN
(SELECT U0."product_id"
FROM "Products_purchase" U0
WHERE (U0."state" = 1
AND U0."user_id" = 5))
AND "Products_product"."state" IN (1,
6,
3)
AND UPPER("Products_product"."title" :: TEXT) LIKE UPPER('%toronto%'))
ORDER BY "Products_product"."title_index" ASC
LIMIT 10;
Run Code Online (Sandbox Code Playgroud)
2
SELECT *
FROM "Products_product"
WHERE ("Products_product"."id" = ANY (ARRAY(
(SELECT U0."product_id"
FROM "Products_purchase" U0
WHERE (U0."state" = 1
AND U0."user_id" = 5))))
AND "Products_product"."state" IN (1,
6,
3)
AND UPPER("Products_product"."title" :: TEXT) LIKE UPPER('%toronto%'))
ORDER BY "Products_product"."title_index" ASC
LIMIT 10; …
Run Code Online (Sandbox Code Playgroud) 我很难理解查询计划缓存如何为pl/pgsql工作.
我想用JOIN
s和IF
s 构建一体化查询,所以我将有多个不同的查询参数,我将在更多的一个表中搜索.
起初我以为使用pl/pgsql会为每个参数组合产生不同的计划,但事实并非如此,因为我有多个表
直接出现在PL/pgSQL函数中的SQL命令必须在每次执行时引用相同的表和列; 也就是说,您不能将参数用作SQL命令中表或列的名称.要解决此限制,您可以使用PL/pgSQL EXECUTE语句构造动态命令 - 代价是执行新的解析分析并在每次执行时构建新的执行计划. 从这里
每次执行一次新的分析都会减慢我的想法.如果我不使用EXECUTE
那么
如果语句没有参数,或者多次执行,则SPI管理器将考虑创建一个不依赖于特定参数值的通用计划,并缓存该计划以供重用.通常,仅当执行计划对其中引用的PL/pgSQL变量的值不是非常敏感时才会发生这种情况.如果是这样,每次产生一个计划都是净胜利.从这里
我应该使用通用计划吗?它更快,还是更慢,因为每次都没有计划?至少它们是缓存的.我的查询对它们的变量很敏感,因为它们是动态的,但是什么
如果是这样,每次产生一个计划都是净胜利.
实际意味着?EXECUTE
每次使用/计划,比通用的更好还是更差?"净胜利"让我困惑.
如果通用计划不准确和EXECUTE
/计划每次都比较慢,那么为什么要使用pl/pgsql呢?我可以用几个ifs编写一个简单的查询.
最重要的是,我无法断定是否EXECUTE/plan each time
比generic cached plan
速度和计划缓存更好或更差.请解释和建议,我很困惑.
作为参考,这是我正在创建的.作品,因为它是现在,但更多的国际单项体育联合会将被添加mytables
和mywhere
DROP FUNCTION IF EXISTS __aa(ii int, fk int);
CREATE FUNCTION __aa(ii int, fk int) RETURNS TABLE(id INTEGER,val text, fd integer) AS $$
DECLARE
myt text;
mytables text;
mywhere text;
BEGIN
mytables := 'dyn_tab2';
mywhere := 'dyn_tab2.id=$1';
IF fk IS NOT …
Run Code Online (Sandbox Code Playgroud) 我有一个 SQL 查询,它在表中查找特定值,然后在三个表之间进行内部联接以获取结果集。这三个表是fabric_barcode_oc
, fabric_barcode_items
&fabric_barcode_rolls
初始查询
查询的初始版本如下
EXPLAIN ANALYZE
SELECT `oc`.`oc_number` AS `ocNumber` , `roll`.`po_number` AS `poNumber` ,
`item`.`item_code` AS `itemCode` , `roll`.`roll_length` AS `rollLength` ,
`roll`.`roll_utilized` AS `rollUtilized`
FROM `fabric_barcode_rolls` AS `roll`
INNER JOIN `fabric_barcode_oc` AS `oc` ON `oc`.`oc_unique_id` = `roll`.`oc_unique_id`
INNER JOIN `fabric_barcode_items` AS `item` ON `item`.`item_unique_id` = `roll`.`item_unique_id_fk`
WHERE BINARY `roll`.`roll_number` = 'dZkzHJ_je8'
Run Code Online (Sandbox Code Playgroud)
EXPLAIN ANALYZE
在此运行时,我得到以下信息
"-> Nested loop inner join (cost=468160.85 rows=582047) (actual time=0.063..254.186 rows=1 loops=1)
-> Nested loop inner join (cost=264444.40 rows=582047) …
Run Code Online (Sandbox Code Playgroud) 我有一个非常简单的表,其中包含 2 列:message_id 和 server_timestamp,但是当我查看此查询的计划时:
sqlite> explain query plan select message_id, server_timestamp from messages group by message_id order by server_timestamp;
selectid|order|from|detail
0|0|0|SCAN TABLE messages USING COVERING INDEX index_messages_id_server_timestamp
0|0|0|USE TEMP B-TREE FOR ORDER BY
Run Code Online (Sandbox Code Playgroud)
其中index_messages_id_server_timestamp 是(message_id, server_timestamp) 上的索引。
为什么这个查询需要使用临时 B 树进行排序?
我想知道运行单个 Postgres 查询时从磁盘(而不是从缓存)读取了多少页(表 + 索引,如果有)。如果有任何方法可以从 EXPLAIN ANALYZE 中提取此信息就更好了。
EXPLAIN ANALYZE SELECT "alerts"."id",
"alerts"."created_at",
't1'::text AS src_table
FROM "alerts"
INNER JOIN "devices"
ON "devices"."id" = "alerts"."device_id"
INNER JOIN "sites"
ON "sites"."id" = "devices"."site_id"
WHERE "sites"."cloud_id" = 111
AND "alerts"."created_at" >= '2019-08-30'
ORDER BY "created_at" DESC limit 9;
Limit (cost=1.15..36021.60 rows=9 width=16) (actual time=30.505..29495.765 rows=9 loops=1)
-> Nested Loop (cost=1.15..232132.92 rows=58 width=16) (actual time=30.504..29495.755 rows=9 loops=1)
-> Nested Loop (cost=0.86..213766.42 rows=57231 width=24) (actual time=0.029..29086.323 rows=88858 loops=1)
-> Index Scan Backward using alerts_created_at_index on alerts (cost=0.43..85542.16 rows=57231 width=24) (actual time=0.014..88.137 rows=88858 …
Run Code Online (Sandbox Code Playgroud) 这是explain.depesz.com上的示例计划:
Limit (cost=65301.950..65301.950 rows=1 width=219) (actual time=886.074..886.074 rows=0 loops=1)
-> Sort (cost=65258.840..65301.950 rows=17243 width=219) (actual time=879.683..885.211 rows=17589 loops=1)
Sort Key: juliet.romeo
Sort Method: external merge Disk: 4664kB
-> Hash Join (cost=30177.210..62214.980 rows=17243 width=219) (actual time=278.986..852.834 rows=17589 loops=1)
Hash Cond: (whiskey_quebec.whiskey_five = juliet.quebec)
-> Bitmap Heap Scan on whiskey_quebec (cost=326.060..21967.630 rows=17243 width=4) (actual time=7.494..65.956 rows=17589 loops=1)
Recheck Cond: (golf = 297)
-> Bitmap Index Scan on kilo (cost=0.000..321.750 rows=17243 width=0) (actual time=4.638..4.638 rows=17589 loops=1)
Index Cond: (golf = 297) …
Run Code Online (Sandbox Code Playgroud)