PostgreSQL基础

第一章:认知篇 ------ 为什么选择 PostgreSQL?

  1. 数据库界的"瑞士军刀":全能型(关系型+JSONB+GIS+全文检索),性能媲美 MongoDB,内置搜索可替代部分 ES。

  2. 极致的严谨性:完美支持 ACID 事务,强类型约束,底层规避 Bug。

  3. 开源与生态:类 BSD 许可,完全免费。Supabase、Neon 等均以其为底层。

  4. 职业护城河:大厂标配(Apple、Instagram),支持窗口函数、CTE、逻辑复制。

第二章:结构篇 ------ 逻辑分层与基础操作

1. 核心层级结构(行政大楼比喻)

实例 (Instance) > 数据库 (Database) > 模式 (Schema) > 表 (Table) > 行与列 (Row & Column)

  • 数据库 :物理隔离,跨库查询需用 dblink 或 FDW。

  • 模式 (Schema) :PG 的灵魂 。默认是 public,建议多用户系统使用独立 Schema 实现逻辑隔离。

2. 库与模式操作代码

sql

复制代码
-- 创建数据库
CREATE DATABASE db_name;
-- 查看数据库
\l 或者 SELECT datname FROM pg_database;
-- 接入数据库
\c db_name;
-- 删除数据库 (需先切换到其他库,且不能有会话连接)
DROP DATABASE db_name;
-- 强制删除
DROP DATABASE db WITH (FORCE);

-- 创建模式
CREATE SCHEMA IF NOT EXISTS storage;
-- 查看模式
\dn
-- 删除模式 (只有模式为空时才能删除)
DROP SCHEMA IF EXISTS storage;
-- 【慎用】级联删除:删除模式以及模式里的所有表、视图、函数等
DROP SCHEMA IF EXISTS storage CASCADE;

3. 表基础操作代码

sql

复制代码
-- 创建表 (带有约束)
CREATE TABLE IF NOT EXISTS storage.files (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, -- 自增主键
    file_id UUID DEFAULT gen_random_uuid(),                 -- uuid
    file_name TEXT NOT NULL,                                -- 不能为空
    file_size BIGINT CHECK (file_size >= 0),                -- 检查约束
    is_public BOOLEAN DEFAULT false,                        -- 默认值
    tags TEXT[],                                            -- 数组类型
    created_at TIMESTAMPTZ DEFAULT NOW()                    -- 带时区的时间
);

-- 修改表 (ALTER TABLE)
ALTER TABLE storage.files ADD COLUMN download_count INT DEFAULT 0; -- 添加字段
ALTER TABLE storage.files ALTER COLUMN file_name TYPE VARCHAR(255); -- 修改字段类型
ALTER TABLE storage.files RENAME COLUMN is_public TO is_shared; -- 重命名
ALTER TABLE storage.files DROP COLUMN tags; -- 删除字段

-- 删除表与清空表
DROP TABLE IF EXISTS storage.files;
DROP TABLE storage.files CASCADE; -- 级联删除
TRUNCATE TABLE storage.files; -- 清空表数据,保留结构
TRUNCATE TABLE storage.files RESTART IDENTITY; -- 清空并重置自增id

-- 查看表信息
SELECT schemaname AS 模式名, tablename AS 表名, tableowner AS 所有人 
FROM pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema') ORDER BY schemaname, tablename;

SELECT column_name AS 字段名, data_type AS 数据类型, is_nullable AS 是否允许为空, column_default AS 默认值, character_maximum_length AS 最大长度 
FROM information_schema.columns WHERE table_name = 'cloud_files' ORDER BY ordinal_position;

第三章:数据建模篇 ------ 类型、约束与表关系

1. 数据类型

  • 核心 :INT/BIGINT, NUMERIC(p,s)(金额),VARCHAR/TEXT,TIMESTAMPZ(带时区)。

  • 特色 :BOOLEAN, JSONB(支持索引,性能极佳),UUID, ARRAY(如 TEXT[]),INET(IP 类型),tsrange(时间范围)。

2. 表关系与约束实战代码

  • 一对一 (1:1) :子表外键设为 PRIMARY KEY 或 UNIQUE。

sql

复制代码
-- 主表:核心账户
CREATE TABLE users (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    username TEXT NOT NULL UNIQUE
);
-- 扩展表:详细资料
CREATE TABLE user_profiles (
    user_id BIGINT PRIMARY KEY, -- 既是主键,也是外键
    avatar_url TEXT,
    bio TEXT,
    CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
  • 一对多 (1:N):在"多"的一方加外键。

sql

复制代码
-- 1. 女神表 (一)
CREATE TABLE goddesses (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    name TEXT NOT NULL,
    star_sign TEXT
);
-- 2. 舔狗表 (多)
CREATE TABLE simps (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    target_id BIGINT NOT NULL, -- 目标女神的 ID (外键)
    nickname TEXT NOT NULL,
    contributed_amount DECIMAL(10, 2) DEFAULT 0,
    CONSTRAINT fk_goddess FOREIGN KEY (target_id) REFERENCES goddesses(id) ON DELETE CASCADE
);
-- 查询连表:查看每位舔狗正在追谁
SELECT s.nickname AS 舔狗, g.name AS 女神, s.contributed_amount AS 贡献值
FROM simps s JOIN goddesses g ON s.target_id = g.id ORDER BY s.contributed_amount DESC;
  • 多对多 (M:N):引入中间表,联合主键。

sql

复制代码
-- 1. 学生表
CREATE TABLE students (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    name TEXT NOT NULL
);
-- 2. 社团表
CREATE TABLE clubs (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    club_name TEXT NOT NULL UNIQUE,
    description TEXT
);
-- 3. 成员关系表 (中间桥梁)
CREATE TABLE memberships (
    student_id BIGINT REFERENCES students(id) ON DELETE CASCADE,
    club_id BIGINT REFERENCES clubs(id) ON DELETE CASCADE,
    joined_at TIMESTAMPTZ DEFAULT NOW(),
    PRIMARY KEY (student_id, club_id) -- 联合主键:保证不会加两次
);
-- 多对多查询:想看 “Go 语言社” 里都有哪些大神?
SELECT c.club_name AS 社团名, s.name AS 成员名, m.joined_at AS 入社时间
FROM clubs c JOIN memberships m ON c.id = m.club_id JOIN students s ON m.student_id = s.id
WHERE c.club_name = 'Go语言社';
  • 表继承 (Inheritance):PG 黑科技。

sql

复制代码
-- 父表:定义基础字段
CREATE TABLE content (title TEXT, author TEXT);
-- 子表:继承基础字段,并增加自己的字段
CREATE TABLE video (duration INT) INHERITS (content);
-- 查询 content 表时,它会自动把 video 表里的数据也查出来。

3. 数据 CRUD 与高级查询代码

sql

复制代码
-- 插入数据 (RETURNING 返回新生成的 UUID)
INSERT INTO files (file_name, file_size, is_public, tags) 
VALUES ('课程大纲.pdf', 1024576, true, ARRAY['教育', 'PDF']);
INSERT INTO files (file_name, file_size) VALUES ('枫枫老师的私房课.zip', 999999) RETURNING file_id, created_at;

-- 更新数据
UPDATE files SET download_count = download_count + 1 WHERE file_name = 'demo.mp4';
UPDATE files SET is_public = false, tags = array_append(tags, '私有') WHERE file_id = '某个UUID';

-- 删除数据
DELETE FROM files WHERE file_id = '某个UUID';
DELETE FROM files WHERE download_count = 0 AND tags @> ARRAY['测试'::text];

-- 排序和分页
SELECT file_name, created_at FROM file_details ORDER BY created_at DESC LIMIT 2 OFFSET 0;

-- 聚合统计 (展开数组并计数)
SELECT uploader_ip, COUNT(*) AS upload_count, SUM(array_length(tags, 1)) AS total_tags
FROM file_details GROUP BY uploader_ip;

-- 数据转换与格式化
SELECT left(detail_id::text, 8) AS short_id, file_name, to_char(created_at, 'YYYY-MM-DD') AS simple_date FROM file_details;

-- JSONB 操作
SELECT file_name, metadata->>'author' AS author FROM file_details WHERE metadata->>'author' = 'Fengfeng'; -- 提取text
SELECT file_name, metadata->'video' AS author FROM file_details WHERE (metadata->'video'->'resolution'->>'width')::int = 1920; -- 提取json对象
SELECT * FROM file_details WHERE metadata ? 'color'; -- 键值对存在性判断

-- INET 网络地址筛选
SELECT * FROM file_details WHERE uploader_ip = '127.0.0.1'; -- 精确匹配
SELECT file_name, uploader_ip FROM file_details WHERE uploader_ip << '172.16.0.0/16'; -- 范围匹配

第四章:高阶提效篇 ------ 视图与 CTE

1. 视图 (View):不存数据只存查询语句,常用于权限控制。

sql

复制代码
-- 创建视图:一次封装,永久受益
CREATE VIEW v_file_detail_full AS
SELECT f.id, f.file_name, u.username AS owner_name, n.node_name AS storage_location, f.created_at
FROM cloud_files f
JOIN users u ON f.user_id = u.id
JOIN storage_nodes n ON f.node_id = n.id;
-- 以后查询只需:
SELECT * FROM v_file_detail_full;

2. CTE (公用表表达式) :使用 WITH 将复杂嵌套 SQL 抽离成变量,提升可读性。

第五章:性能引擎篇 ------ 索引与事务锁

1. 索引代码与原理

  • 原理:B-Tree 平衡多路查找树,将全表扫描 O(n)O(n) 降至 O(log⁡mn)O(logm​n)。

  • 创建不同类型的索引:

sql

复制代码
-- 显式指定或默认不写都是 B-Tree
CREATE INDEX idx_file_name ON cloud_files USING btree (file_name);
-- 仅适用于 = 查询
CREATE INDEX idx_file_hash ON cloud_files USING hash (file_name);
-- 复合索引:(user_id, file_type) 遵循最左匹配原则
CREATE INDEX idx_user_file_type ON cloud_files (user_id, file_type);
-- GIN 索引:标签查询或 JSONB 格式元数据的“神器”
CREATE INDEX idx_files_tags ON cloud_files USING gin (tags);
CREATE INDEX idx_files_meta ON cloud_files USING gin (meta_data jsonb_path_ops);
-- 唯一索引
CREATE UNIQUE INDEX idx_file_md5 ON cloud_files (file_md5);

-- 分析查询性能
EXPLAIN ANALYZE SELECT * FROM cloud_files WHERE file_name = 'file_999999.pdf';
  • 索引失效场景 :LIKE '%xxx'(左模糊)、函数操作(如 UPPER(name))、类型隐式转换(数字查字符串)、不符合复合索引最左匹配。

2. 事务与锁代码

  • 事务 ACID:原子性、一致性、隔离性、持久性。

sql

复制代码
BEGIN; -- 开启事务,立下“生死状”
-- 1. 扣钱
UPDATE accounts SET balance = balance - 100 WHERE username = '小红';
-- 2. 增加会员时长
UPDATE members SET expire_date = expire_date + INTERVAL '1 year' WHERE username = '小红';
-- 检查一下:如果钱扣对了,会员也加了
COMMIT; -- 确认无误,正式写入硬盘

-- 如果中途出错:
ROLLBACK; -- 刚才的所有操作全部撤销,像没发生过一样
  • 锁机制(三大层次):

sql

复制代码
-- 手动锁定表 (大面积维护时使用,不希望别人干扰)
BEGIN;
LOCK TABLE my_table IN ACCESS EXCLUSIVE MODE; -- 彻底锁死表
-- 执行操作...
COMMIT;

-- 使用建议锁 (Advisory Locks):程序员自定义的逻辑锁,不锁表/行
SELECT pg_advisory_lock(12345); -- 获取编号为 12345 的逻辑锁
-- 执行你的业务逻辑...
SELECT pg_advisory_unlock(12345); -- 释放锁

-- 如何查看当前的锁? (排查数据库“卡住了”)
SELECT * FROM pg_locks l JOIN pg_stat_activity a ON l.pid = a.pid;

第六章:杀手锏扩展篇 ------ 一库多用

1. 全文搜索 (替代 Elasticsearch)

sql

复制代码
-- 查看并安装扩展
SELECT * FROM pg_available_extensions;
SELECT * FROM pg_extension;

-- 英文全文检索示例 (动态分词)
SELECT title, content FROM posts 
WHERE to_tsvector('english', title || ' ' || content) @@ to_tsquery('english', 'PostgreSQL | Guide');

-- 性能优化:预分词 (建立 STORED 列并加 GIN 索引)
CREATE TABLE posts1 (
    id SERIAL PRIMARY KEY,
    title TEXT NOT NULL,
    content TEXT,
    searchable_index_col tsvector GENERATED ALWAYS AS (to_tsvector('english', title || ' ' || content)) STORED
);
CREATE INDEX idx_posts_search ON posts1 USING GIN (searchable_index_col);
-- 查询时:
SELECT title, content FROM posts1 WHERE searchable_index_col @@ to_tsquery('english', 'PostgreSQL');

-- 中文分词 (需使用 Docker 镜像并初始化)
CREATE EXTENSION IF NOT EXISTS zhparser;
CREATE TEXT SEARCH CONFIGURATION chinese (PARSER = zhparser);
ALTER TEXT SEARCH CONFIGURATION chinese ADD MAPPING FOR n,v,a,i,e,l WITH simple;

2. 地理信息 (PostGIS / earthdistance)

sql

复制代码
-- 安装扩展
CREATE EXTENSION cube;
CREATE EXTENSION earthdistance;

-- 计算 (经度1, 纬度1) 到 (经度2, 纬度2) 的距离
SELECT earth_distance(
    ll_to_earth(23.45, 113.12),
    ll_to_earth(23.50, 113.15)
) AS distance_meters;
-- PostGIS 高级用法:坐标系转换
-- ST_Transform(geometry, 4326)

3. 向量数据库 (pgvector)

bash

复制代码
# Docker 运行 pgvector
docker pull pgvector/pgvector:pg16
docker run -d --name pg-vector -e POSTGRES_PASSWORD=root -p 15432:5432 pgvector/pgvector:pg16
  • 三大核心操作符 :<=>(余弦距离,RAG 最常用)、<->(L2 欧氏距离)、<#>(内积)。

第七章:生产运维篇 ------ 安全与备份

1. 用户与角色 (RBAC) 代码

sql

复制代码
-- 1. 创建一个组 (不准登录)
CREATE ROLE managers;
-- 2. 创建一个用户 (准许登录)
CREATE USER fengfeng WITH PASSWORD 'fengfeng';
-- 3. 让“用户”加入“组”
GRANT managers TO fengfeng;

-- 示例:给用户设置某一个库的只读权限
-- 1. 创建用户
CREATE USER reader_user WITH PASSWORD 'fengfeng';
-- 2. 基础进门权
GRANT CONNECT ON DATABASE your_db_name TO reader_user; -- 可以进入db这个库
GRANT USAGE ON SCHEMA public TO reader_user; -- 可以进入public这个模式
-- 3. 核心只读权 (现在的表 + 序列)
GRANT SELECT ON ALL TABLES IN SCHEMA public TO reader_user;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO reader_user;
-- 4. 自动化 (未来的表)
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO reader_user;

2. 备份与恢复代码

bash

复制代码
# pg_dump 单库备份 (纯文本 SQL 格式)
pg_dump -U postgres -d db > db_0414.sql

# pg_dump 单库备份 (压缩的二进制格式,推荐:体积小,支持并行恢复)
pg_dump -U postgres -F c -d db > db_0414.bak

# pg_dumpall 全库备份 (包含所有数据库、用户和权限)
set PGPASSWORD=root
pg_dumpall -U postgres > all_databases_backup.sql

# 恢复纯文本 SQL 备份
psql -U postgres -d db1 < db_0414.sql

# 恢复二进制备份 (必须用 pg_restore)
pg_restore -U postgres -d db2 -c db_0414.bak
# -c 代表先清理(删除)旧表再恢复,防止冲突

# 恢复 pg_dumpall 的全库备份
psql -U postgres -f all_databases_backup.sql postgres
相关推荐
zyseo81 小时前
谷歌SEO 站点地图优化实战:sitemap 是索引候选清单的运营工具
网络·数据库·经验分享·笔记·搜索引擎
wespaul1 小时前
VeapAI 自然语言操作实战|第 04 篇:系统数据加工——把系统自身的元数据吃成知识
java·大数据·运维·数据库·人工智能
用户84913717547161 小时前
数据库迁移总出问题?学会这个工具,让团队协作效率翻倍!
数据库·sql
幼儿园蛋小黑1 小时前
SPI 子系统:从原理到实践
java·前端·数据库
安妮细水长流1 小时前
【无标题】
数据库·mongodb
KKKlucifer2 小时前
从规则到大模型:数据分类分级平台的能力分野与场景适配
大数据·数据库·分类
架构师伯子明2 小时前
QT+Opengl (1):渲染一个三角形
数据库
A-刘晨阳2 小时前
金仓时序数据库:以高效压缩、快速写入与时序优化,破解工业海量数据管理难题
数据库·时序数据库
2603_965148112 小时前
终极清单:构建自动化选品比价系统的所有组件与资源
大数据·运维·数据库·数据挖掘·自动化