PG 实战笔记

PG 实战笔记
PostgreSQL - PopSQL
PopSQL is a unified SQL collaboration workspace that connects everyone in the data analysis process so you can obtain better insights by asking the right questions, together.
个人习惯,数据库尽量规范化,不要提早做优化。性能出了问题先尝试缓存、读写分离等等,最后再考虑反规范化。

Docker 启动

docker run -p 3306:3306  --name mysql -e MYSQL_ROOT_PASSWORD=password -d mysql

关联统计

SELECT *,(select count(Stories.id) from Stories where project_id=projects.id)storyCount FROM `projects` WHERE `projects`.`deleted_at` IS NULL LIMIT 10

JSON的一些操作

使用全文搜索JSONB

SELECT mark.note.comment, id, content
FROM mark.note
WHERE comment::text similar to '%consumers%'
   or content similar to '%consumers%'
order by updated_at DESC;

自动生成uuid

CREATE EXTENSION pgcrypto;

雪花ID SQL函数

生成序列和创建函数要分步执行

-- 创建序列来替代表
CREATE SEQUENCE IF NOT EXISTS snowflake_sequence;

-- 创建雪花ID生成函数
CREATE OR REPLACE FUNCTION generate_snowflake_id(node_id int)
RETURNS bigint AS $$
DECLARE
    -- 常量定义
    epoch bigint := 1640995200000;  -- 2022-01-01 作为纪元
    timestamp_bits int := 41;
    node_id_bits int := 10;
    sequence_bits int := 12;
    
    -- 计算最大值
    max_node_id bigint := (1 << node_id_bits) - 1;
    max_sequence bigint := (1 << sequence_bits) - 1;
    
    -- 变量定义
    timestamp bigint;
    sequence bigint;
    last_timestamp bigint := 0;
BEGIN
    -- 检查节点ID是否有效
    IF node_id < 0 OR node_id > max_node_id THEN
        RAISE EXCEPTION 'Invalid node ID: %', node_id;
    END IF;

    -- 获取当前时间戳(毫秒)
    timestamp := (EXTRACT(EPOCH FROM clock_timestamp()) * 1000)::bigint - epoch;
    
    -- 如果时间戳回退,抛出异常
    IF timestamp < last_timestamp THEN
        RAISE EXCEPTION 'Clock moved backwards. Refusing to generate id for % milliseconds', last_timestamp - timestamp;
    END IF;
    
    -- 如果是同一毫秒,增加序列号
    IF timestamp = last_timestamp THEN
        sequence := (nextval('snowflake_sequence') - 1) & max_sequence;
        -- 如果序列号溢出,等待下一毫秒
        IF sequence = 0 THEN
            timestamp := timestamp + 1;
        END IF;
    ELSE
        -- 不同毫秒,重置序列号
        sequence := 0;
        last_timestamp := timestamp;
        -- 重置序列
        PERFORM setval('snowflake_sequence', 1, false);
    END IF;
    
    -- 生成并返回雪花ID
    RETURN (
        (timestamp << (node_id_bits + sequence_bits)) |
        (node_id << sequence_bits) |
        sequence
    );
END;
$$ LANGUAGE plpgsql;

使用方法:id_generator()

随机查找

CREATE
OR REPLACE FUNCTION npmvs.lucky_packages(num integer) RETURNS SETOF npmvs.package LANGUAGE sql STABLE AS $ function $
select
  *
from
  npmvs.package
order by
  random()
limit
  num $ function $

OR

CREATE
OR REPLACE FUNCTION npmvs.lucky_tags(num integer) RETURNS SETOF npmvs.tag LANGUAGE sql STABLE AS $ function $
select
  id,
  name
from
  npmvs.tag
order by
  random()
limit
  5 $ function $