建站好的公司,鞍山网上制作网站,长治建设工程交易网,南宁网站推广营销一、LOCALE 与 “operator class”
在PostgreSQL里#xff0c;LOCALE默认使用C的本地化规则。LOCALE是一种文化偏好的区域设置#xff0c;包括字母表、排序、数字格式等。
LOCALE里有一个比较重要的规则LC_COLLATE#xff0c;即排序方式(Collation)#xff0c;它会对数据…一、LOCALE 与 “operator class”
在PostgreSQL里LOCALE默认使用C的本地化规则。LOCALE是一种文化偏好的区域设置包括字母表、排序、数字格式等。
LOCALE里有一个比较重要的规则LC_COLLATE即排序方式(Collation)它会对数据库行为有显著影响。
当数据库里运行一个like查询DB上使用非C LOCALE普通索引可能不支持like操作普通索引创建时我们通常不会显式指定operator class示例如下
CREATE INDEX ON users (email);那下面like查询的执行计划可以看到走全表扫描。
postgres# EXPLAIN SELECT * FROM users WHERE email LIKE lukas%;QUERY PLAN
-------------------------------------------------------------------------Seq Scan on users (cost10000000000.00..10000000001.26 rows1 width4463)Filter: ((email)::text ~~ lukas%::text)
(2 rows)如果进行引导明确使用文本模式操作符text_pattern_ops。
CREATE INDEX ON users (email text_pattern_ops);那下面的执行计划可以看到也能正常使用索引。
postgres# EXPLAIN SELECT * FROM users WHERE email LIKE lukas%;QUERY PLAN
--------------------------------------------------------------------------Index Scan using users_email_idx on users (cost0.14..8.16 rows1 width4463)Index Cond: (((email)::text ~~ lukas::text) AND ((email)::text ~~ lukasA::text))Filter: ((email)::text ~~ lukas%::text)
(3 rows)二、Trigger 与 Transition Table
trigger触发器通常以串行方式工作例如下面为了提高item大表count总数的性能使用触发器更新随时将总数更新到sum表便于快速统计。
CREATE TABLE item (id bigint GENERATED ALWAYS AS IDENTITY,value bigint NOT NULL
);CREATE TABLE sum (total bigint NOT NULL
);INSERT INTO sum VALUES (0);CREATE FUNCTION add_to_sum() RETURNS triggerLANGUAGE plpgsql AS
$$BEGINUPDATE sum SET total total NEW.value;RETURN NEW;
END;$$;CREATE CONSTRAINT TRIGGER add_to_sumAFTER INSERT ON itemDEFERRABLE INITIALLY DEFERREDFOR EACH ROWEXECUTE FUNCTION add_to_sum();但是如果item表有比较频繁的批量操作尤其还在一个事务里会引起dead tuple回收不及时那基于触发器统计更新数据会变得越来越慢。
此时使用触发器的transition table过渡表特性在内存中批量处理性能提升会比较明显。
DROP TRIGGER add_to_sum ON item;CREATE OR REPLACE FUNCTION add_to_sum() RETURNS triggerLANGUAGE plpgsql AS
$$BEGINUPDATE sum SET total total (SELECT sum(value) FROM new_rows);RETURN NULL;
END;$$;CREATE TRIGGER add_to_sumAFTER INSERT ON itemREFERENCING NEW TABLE AS new_rowsFOR EACH STATEMENTEXECUTE FUNCTION add_to_sum();三、Case 与 Filter
在PostgreSQL的聚合函数中可以使用CASE或FILTER来过来数据
查询一使用case
SELECTfa.actor_id,SUM(CASE WHEN rating R THEN length END),SUM(CASE WHEN rating PG THEN length END)
FROM film_actor AS fa
LEFT JOIN film AS f ON f.film_id fa.film_id
GROUP BY fa.actor_id查询二使用filter
SELECTfa.actor_id,SUM(length) FILTER (WHERE rating R),SUM(length) FILTER (WHERE rating PG),
FROM film_actor AS fa
LEFT JOIN film AS f ON f.film_id fa.film_id
GROUP BY fa.actor_id上面的两个查询功能是一样的有人在docker运行PostgreSQL 15的环境测试对比使用CASE语法会有8%的性能损失。FILTER的性能更好且语法更简洁。