@gordon.gan/specflow 1.4.0-beta → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/prompts/approval/database-guidance.md +79 -0
  4. package/prompts/approval/generate.md +569 -290
  5. package/skills/database/LICENSE +405 -0
  6. package/skills/database/ORIGIN.md +6 -0
  7. package/skills/database/README.md +30 -0
  8. package/skills/database/elasticsearch/LICENSE.txt +202 -0
  9. package/skills/database/elasticsearch/SKILL.md +199 -0
  10. package/skills/database/elasticsearch/examples/01-fulltext-search.md +215 -0
  11. package/skills/database/elasticsearch/examples/02-aggregation-report.md +206 -0
  12. package/skills/database/elasticsearch/examples/03-reindex-zero-downtime.md +200 -0
  13. package/skills/database/elasticsearch/examples/04-cluster-monitoring.md +204 -0
  14. package/skills/database/elasticsearch/references/01-query-dsl-fulltext.md +162 -0
  15. package/skills/database/elasticsearch/references/02-query-dsl-term.md +210 -0
  16. package/skills/database/elasticsearch/references/03-aggregations-metric.md +161 -0
  17. package/skills/database/elasticsearch/references/04-aggregations-bucket.md +236 -0
  18. package/skills/database/elasticsearch/references/05-mapping-types.md +134 -0
  19. package/skills/database/elasticsearch/references/06-analyzers.md +187 -0
  20. package/skills/database/elasticsearch/references/07-cluster-ops.md +225 -0
  21. package/skills/database/elasticsearch/references/08-elk-integration.md +170 -0
  22. package/skills/database/mysql/SKILL.md +195 -0
  23. package/skills/database/mysql/examples/01-connection-pool.md +75 -0
  24. package/skills/database/mysql/examples/02-slow-query-optimization.md +98 -0
  25. package/skills/database/mysql/examples/03-master-slave-setup.md +144 -0
  26. package/skills/database/mysql/examples/04-backup-strategy.md +212 -0
  27. package/skills/database/mysql/references/01-functions-string.md +103 -0
  28. package/skills/database/mysql/references/02-functions-date.md +152 -0
  29. package/skills/database/mysql/references/03-functions-aggregate-window.md +167 -0
  30. package/skills/database/mysql/references/04-functions-json.md +129 -0
  31. package/skills/database/mysql/references/05-sql-ddl-types.md +235 -0
  32. package/skills/database/mysql/references/06-index-optimization.md +232 -0
  33. package/skills/database/mysql/references/07-replication-ha.md +213 -0
  34. package/skills/database/mysql/references/08-backup-restore.md +207 -0
  35. package/skills/database/mysql/references/09-advanced-features.md +345 -0
  36. package/skills/database/oracle/LICENSE.txt +202 -0
  37. package/skills/database/oracle/SKILL.md +238 -0
  38. package/skills/database/oracle/examples/01-plsql-procedure.md +90 -0
  39. package/skills/database/oracle/examples/02-awr-analysis.md +99 -0
  40. package/skills/database/oracle/examples/03-rman-backup.md +108 -0
  41. package/skills/database/oracle/examples/04-dataguard-setup.md +146 -0
  42. package/skills/database/oracle/references/01-functions-string.md +91 -0
  43. package/skills/database/oracle/references/02-functions-date.md +71 -0
  44. package/skills/database/oracle/references/03-analytic-functions.md +103 -0
  45. package/skills/database/oracle/references/04-plsql-guide.md +303 -0
  46. package/skills/database/oracle/references/05-performance-tuning.md +164 -0
  47. package/skills/database/oracle/references/06-backup-recovery.md +115 -0
  48. package/skills/database/oracle/references/07-dataguard-rac.md +76 -0
  49. package/skills/database/oracle/references/08-security.md +170 -0
  50. package/skills/database/oracle/references/09-sql-syntax.md +152 -0
  51. package/skills/database/oracle/references/10-features.md +174 -0
  52. package/skills/database/postgresql/LICENSE.txt +202 -0
  53. package/skills/database/postgresql/SKILL.md +182 -0
  54. package/skills/database/postgresql/examples/.gitkeep +0 -0
  55. package/skills/database/postgresql/examples/01-jsonb-query.md +72 -0
  56. package/skills/database/postgresql/examples/02-cte-recursive.md +110 -0
  57. package/skills/database/postgresql/examples/03-performance-tuning.md +114 -0
  58. package/skills/database/postgresql/examples/04-streaming-replication.md +113 -0
  59. package/skills/database/postgresql/references/.gitkeep +0 -0
  60. package/skills/database/postgresql/references/01-functions-string.md +174 -0
  61. package/skills/database/postgresql/references/02-functions-datetime.md +54 -0
  62. package/skills/database/postgresql/references/03-functions-aggregate-window.md +142 -0
  63. package/skills/database/postgresql/references/04-functions-jsonb.md +117 -0
  64. package/skills/database/postgresql/references/05-fulltext-search.md +109 -0
  65. package/skills/database/postgresql/references/06-index-types.md +95 -0
  66. package/skills/database/postgresql/references/07-partition-fdw.md +133 -0
  67. package/skills/database/postgresql/references/08-replication-backup.md +215 -0
  68. package/skills/database/redis/LICENSE.txt +202 -0
  69. package/skills/database/redis/SKILL.md +922 -0
  70. package/skills/database/redis/examples/01-cache-usage.md +104 -0
  71. package/skills/database/redis/examples/02-session-storage.md +72 -0
  72. package/skills/database/redis/examples/03-leaderboard.md +63 -0
  73. package/skills/database/redis/examples/04-redis-cluster-setup.md +70 -0
  74. package/skills/database/redis/examples/05-stream-queue.md +65 -0
  75. package/skills/database/redis/references/command-quick-ref.md +180 -0
  76. package/skills/database/redis/references/commands-admin-key.md +413 -0
  77. package/skills/database/redis/references/commands-set-sorted-advanced.md +539 -0
  78. package/skills/database/redis/references/commands-string-hash-list.md +458 -0
  79. package/skills/database/redis/references/memory-optimization.md +150 -0
  80. package/skills/database/redis/references/redis-conf-production.md +139 -0
  81. package/skills/specflow-approval/SKILL.md +100 -181
  82. package/templates/approval.md +295 -221
@@ -0,0 +1,117 @@
1
+ # JSONB 函数与操作详解
2
+
3
+ ## 访问操作符
4
+
5
+ ```sql
6
+ -- -> 返回 JSONB, ->> 返回 TEXT
7
+ SELECT
8
+ config -> 'theme' AS theme_jsonb, -- "dark"
9
+ config ->> 'theme' AS theme_text, -- dark
10
+ config -> 'notifications' -> 'email' AS email_jsonb,
11
+ config #>> '{preferences, language}' AS lang
12
+
13
+ FROM user_configs WHERE user_id = 1;
14
+
15
+ -- #> / #>> 路径访问
16
+ SELECT config #> '{preferences, timezone}' AS tz,
17
+ config #>> '{notifications, push}' AS push
18
+ FROM user_configs WHERE user_id = 1;
19
+ ```
20
+
21
+ ## 包含与存在操作
22
+
23
+ ```sql
24
+ -- @> — 包含(业务场景:查询包含特定配置的用户)
25
+ SELECT user_id, config FROM user_configs
26
+ WHERE config @> '{"notifications": {"email": true}}';
27
+
28
+ -- ? — 是否存在键
29
+ SELECT user_id FROM user_configs WHERE config ? 'trust_score';
30
+
31
+ -- ?| — 存在任意键
32
+ SELECT user_id FROM user_configs WHERE config ?| ARRAY['trust_score', 'vip_level'];
33
+
34
+ -- ?& — 包含所有键
35
+ SELECT user_id FROM user_configs WHERE config ?& ARRAY['theme', 'notifications'];
36
+ ```
37
+
38
+ ## 修改函数
39
+
40
+ ```sql
41
+ -- || — JSONB 合并
42
+ UPDATE user_configs SET config = config || '{"vip_level": 2}' WHERE user_id = 1;
43
+
44
+ -- JSONB_SET — 设置路径值
45
+ UPDATE user_configs SET config = JSONB_SET(config, '{notifications, email}', 'false'::JSONB)
46
+ WHERE user_id = 1;
47
+
48
+ -- JSONB_INSERT — 插入不覆盖 (PG 9.6+)
49
+ SELECT JSONB_INSERT('{"a":1,"b":2}'::JSONB, '{c}', '3'::JSONB);
50
+
51
+ -- JSONB_STRIP_NULLS — 移除 null
52
+ SELECT JSONB_STRIP_NULLS('{"a":1,"b":null}'::JSONB); -- {"a": 1}
53
+ ```
54
+
55
+ ## 构建函数
56
+
57
+ ```sql
58
+ -- JSONB_BUILD_OBJECT / JSONB_BUILD_ARRAY
59
+ SELECT JSONB_BUILD_OBJECT(
60
+ 'id', 101, 'name', 'Alice',
61
+ 'roles', JSONB_BUILD_ARRAY('admin', 'editor'),
62
+ 'meta', JSONB_BUILD_OBJECT('last_login', NOW())
63
+ );
64
+ ```
65
+
66
+ ## 展开函数
67
+
68
+ ```sql
69
+ -- JSONB_EACH — 展开为 (key, value) 行集
70
+ SELECT * FROM JSONB_EACH((SELECT config FROM user_configs WHERE user_id = 1));
71
+
72
+ -- JSONB_EACH_TEXT — 展开为 (key, text_value)
73
+ SELECT * FROM JSONB_EACH_TEXT((SELECT config FROM user_configs WHERE user_id = 1));
74
+
75
+ -- JSONB_OBJECT_KEYS — 仅返回键
76
+ SELECT * FROM JSONB_OBJECT_KEYS((SELECT config FROM user_configs WHERE user_id = 1));
77
+
78
+ -- JSONB_EXTRACT_PATH — 提取路径
79
+ SELECT JSONB_EXTRACT_PATH(config, 'preferences', 'language') FROM user_configs;
80
+ ```
81
+
82
+ ## 类型检查与格式化
83
+
84
+ ```sql
85
+ -- JSONB_TYPEOF (PG 14+)
86
+ SELECT JSONB_TYPEOF(config -> 'theme'), -- string
87
+ JSONB_TYPEOF(config -> 'tags'), -- array
88
+ JSONB_TYPEOF(config -> 'trust_score') -- number
89
+ FROM user_configs WHERE user_id = 1;
90
+
91
+ -- JSONB_PRETTY (PG 14+)
92
+ SELECT JSONB_PRETTY(config) FROM user_configs WHERE user_id = 1;
93
+ ```
94
+
95
+ ## GIN 索引
96
+
97
+ ```sql
98
+ -- 标准 GIN
99
+ CREATE INDEX idx_config_gin ON user_configs USING GIN (config);
100
+
101
+ -- jsonb_path_ops(更小更快,不支持 ? 操作符)
102
+ CREATE INDEX idx_config_path ON user_configs USING GIN (config jsonb_path_ops);
103
+ ```
104
+
105
+ ## 完整示例表
106
+
107
+ ```sql
108
+ CREATE TABLE user_configs (
109
+ id BIGSERIAL PRIMARY KEY,
110
+ user_id INTEGER NOT NULL,
111
+ config JSONB NOT NULL DEFAULT '{}'
112
+ );
113
+
114
+ INSERT INTO user_configs (user_id, config) VALUES
115
+ (1, '{"theme":"dark","notifications":{"email":true},"preferences":{"language":"zh-CN","timezone":"Asia/Shanghai"},"tags":["developer","premium"],"trust_score":4.5}'),
116
+ (2, '{"theme":"light","notifications":{"email":false},"preferences":{"language":"en","timezone":"America/New_York"},"tags":["basic"]}');
117
+ ```
@@ -0,0 +1,109 @@
1
+ # 全文搜索详解
2
+
3
+ ## 基础概念
4
+
5
+ PostgreSQL 全文搜索基于 **tsvector** (文本搜索向量) 和 **tsquery** (文本搜索查询),配合 GIN 索引实现高效搜索。
6
+
7
+ ## 建表与索引
8
+
9
+ ```sql
10
+ CREATE TABLE documents (
11
+ id SERIAL PRIMARY KEY,
12
+ title TEXT NOT NULL,
13
+ body TEXT NOT NULL,
14
+ body_tsv TSVECTOR GENERATED ALWAYS AS (to_tsvector('english', body)) STORED
15
+ );
16
+
17
+ CREATE INDEX idx_documents_body_tsv ON documents USING GIN (body_tsv);
18
+
19
+ INSERT INTO documents (title, body) VALUES
20
+ ('PostgreSQL Full Text Search',
21
+ 'PostgreSQL provides full-text search capabilities out of the box.'),
22
+ ('Indexing Strategies',
23
+ 'Proper indexing is crucial for database performance. GIN indexes are optimized for full-text search.'),
24
+ ('Database Performance Tuning',
25
+ 'Performance tuning involves many aspects including query optimization, indexing strategy, and hardware configuration.');
26
+ ```
27
+
28
+ ## 核心函数
29
+
30
+ ```sql
31
+ -- to_tsvector — 文本转搜索向量(停用词被移除, 动词被词根化)
32
+ SELECT to_tsvector('english', 'The quick brown fox jumps over the lazy dog');
33
+ -- 'brown':3 'dog':9 'fox':4 'jump':5 'lazi':8 'quick':2
34
+
35
+ -- to_tsquery — 文本转搜索查询
36
+ SELECT to_tsquery('english', 'search & indexing');
37
+ -- 'search' & 'index'
38
+
39
+ -- plainto_tsquery — 简单转换(空格分隔的单词自动加 &)
40
+ SELECT plainto_tsquery('english', 'full text search');
41
+ -- 'full' & 'text' & 'search'
42
+ ```
43
+
44
+ ## 匹配查询
45
+
46
+ ```sql
47
+ -- @@ — 全文搜索匹配操作符
48
+ SELECT id, title FROM documents
49
+ WHERE body_tsv @@ to_tsquery('english', 'search & index');
50
+
51
+ -- plainto_tsquery 简化写法
52
+ SELECT id, title FROM documents
53
+ WHERE body_tsv @@ plainto_tsquery('english', 'full text search');
54
+
55
+ -- 直接对原始列搜索(不依赖 tsvector 列)
56
+ SELECT id, title FROM documents
57
+ WHERE to_tsvector('english', body) @@ to_tsquery('english', 'search');
58
+ ```
59
+
60
+ ## 排序与高亮
61
+
62
+ ```sql
63
+ -- ts_rank / ts_rank_cd — 相关性排序
64
+ SELECT id, title, ts_rank(body_tsv, query) AS rank
65
+ FROM documents, to_tsquery('english', 'search & indexing') AS query
66
+ WHERE body_tsv @@ query ORDER BY rank DESC;
67
+
68
+ -- ts_headline — 高亮摘要
69
+ SELECT id, ts_headline('english', body, query,
70
+ 'StartSel=<mark>, StopSel=</mark>, MaxWords=30, MinWords=10') AS highlighted
71
+ FROM documents, plainto_tsquery('english', 'full text search') AS query
72
+ WHERE body_tsv @@ query;
73
+ ```
74
+
75
+ ## 短语搜索
76
+
77
+ ```sql
78
+ -- <-> : 相邻单词
79
+ SELECT * FROM documents
80
+ WHERE body_tsv @@ to_tsquery('english', 'full <-> text <-> search');
81
+
82
+ -- <N> : 相隔最多 N 个词
83
+ SELECT * FROM documents
84
+ WHERE body_tsv @@ to_tsquery('english', 'performance <2> tuning');
85
+ -- 匹配 "performance tuning" 或 "performance and tuning"
86
+ ```
87
+
88
+ ## 中文全文搜索
89
+
90
+ ```sql
91
+ -- 需要 zhparser 或 jieba 扩展
92
+ -- CREATE EXTENSION zhparser;
93
+ -- CREATE TEXT SEARCH CONFIGURATION chinese (PARSER = zhparser);
94
+ -- ALTER TEXT SEARCH CONFIGURATION chinese ADD MAPPING FOR n,v,a,i,e,l WITH simple;
95
+ -- SELECT to_tsvector('chinese', '数据库性能优化技巧');
96
+ ```
97
+
98
+ ## 多语言与自定义配置
99
+
100
+ ```sql
101
+ -- simple: 不做词干分析
102
+ SELECT to_tsvector('simple', 'running runs ran'); -- 'running':1 'runs':2 'ran':3
103
+
104
+ -- english: 词干分析
105
+ SELECT to_tsvector('english', 'running runs ran'); -- 'run':1,2,3
106
+
107
+ -- 创建自定义字典
108
+ CREATE TEXT SEARCH DICTIONARY my_dict (TEMPLATE = pg_catalog.simple, ...);
109
+ ```
@@ -0,0 +1,95 @@
1
+ # 索引类型与视图详解
2
+
3
+ ## 6种索引类型
4
+
5
+ | 索引类型 | 适用场景 | 操作符 | 典型用途 |
6
+ |---------|---------|--------|---------|
7
+ | **B-Tree** (默认) | 等值/范围查询 | =, <, <=, >, >=, BETWEEN, IN, IS NULL, LIKE ('abc%') | 主键、外键、排序字段 |
8
+ | **Hash** | 等值查询 | = | 长随机值的等值比较 (有限用途) |
9
+ | **GiST** | 几何/全文/范围 | &&, <@, @>, <<, >>, ~= | PostGIS、范围排除约束 |
10
+ | **GIN** | 复合值索引 | @>, <@, ?, ?|, ?&, @@ | JSONB、数组、全文搜索 |
11
+ | **BRIN** | 大表顺序相关数据 | =, <, <=, >, >=, BETWEEN | 时间序列、日志表 (节省 95%+ 空间) |
12
+ | **SP-GiST** | 空间分区/聚类 | 同 GiST | 四叉树、k-d 树、前缀树 |
13
+
14
+ ## 索引创建
15
+
16
+ ```sql
17
+ -- B-Tree
18
+ CREATE INDEX idx_users_email ON users (email);
19
+ CREATE INDEX idx_orders_created_at ON orders (created_at DESC);
20
+ CREATE INDEX idx_orders_user_status ON orders (user_id, status);
21
+
22
+ -- 复合索引列顺序: 等值在前,范围在后,选择性高的在前
23
+ -- ✅ WHERE user_id = 1 AND status = 'paid' → 索引 (user_id, status) 最优
24
+ -- ❌ WHERE status = 'paid' AND created_at > '2024-01-01' → 索引 (created_at, status) 更好
25
+
26
+ -- 部分索引(仅索引活跃用户,更小更快)
27
+ CREATE INDEX idx_users_active ON users (email) WHERE is_active = TRUE;
28
+
29
+ -- 覆盖索引 / INCLUDE (PG 11+, 避免回表)
30
+ CREATE INDEX idx_orders_covering ON orders (user_id, status) INCLUDE (total_amount, created_at);
31
+
32
+ -- Hash 索引
33
+ CREATE INDEX idx_users_email_hash ON users USING HASH (email);
34
+
35
+ -- GIN 索引
36
+ CREATE INDEX idx_articles_body_tsv ON articles USING GIN (body_tsv);
37
+ CREATE INDEX idx_config_gin ON user_configs USING GIN (config);
38
+ CREATE INDEX idx_articles_tags_gin ON articles USING GIN (tags);
39
+ CREATE INDEX idx_config_path ON user_configs USING GIN (config jsonb_path_ops);
40
+
41
+ -- GiST 索引
42
+ CREATE INDEX idx_room_bookings_period ON room_bookings USING GIST (period);
43
+
44
+ -- BRIN 索引(大表时序数据,极大节省空间)
45
+ CREATE INDEX idx_orders_brin ON orders USING BRIN (created_at) WITH (pages_per_range = 32);
46
+
47
+ -- CONCURRENTLY — 在线建索引(不阻塞写)
48
+ CREATE INDEX CONCURRENTLY idx_orders_user_id ON orders (user_id);
49
+ ```
50
+
51
+ ## 索引维护
52
+
53
+ ```sql
54
+ -- DROP INDEX CONCURRENTLY — 在线删除
55
+ DROP INDEX CONCURRENTLY IF EXISTS idx_orders_old;
56
+
57
+ -- REINDEX — 重建索引(索引膨胀时)
58
+ REINDEX INDEX idx_orders_user_id;
59
+ REINDEX TABLE orders;
60
+ REINDEX DATABASE mydb;
61
+
62
+ -- REINDEX CONCURRENTLY — 在线重建 (PG 12+)
63
+ REINDEX INDEX CONCURRENTLY idx_orders_user_id;
64
+ ```
65
+
66
+ ## 视图 (View)
67
+
68
+ ```sql
69
+ -- 普通视图 — 虚拟表
70
+ CREATE VIEW user_order_summary AS
71
+ SELECT u.id, u.username, COUNT(o.id) AS total_orders,
72
+ COALESCE(SUM(o.total_amount), 0) AS total_spent,
73
+ MAX(o.created_at) AS last_order_date
74
+ FROM users u LEFT JOIN orders o ON o.user_id = u.id
75
+ GROUP BY u.id, u.username;
76
+
77
+ -- WITH CHECK OPTION — 确保更新满足视图条件
78
+ CREATE VIEW paid_orders AS SELECT * FROM orders WHERE status = 'paid'
79
+ WITH CHECK OPTION;
80
+
81
+ -- 物化视图 — 物理存储的快照
82
+ CREATE MATERIALIZED VIEW mv_monthly_sales AS
83
+ SELECT DATE_TRUNC('month', o.created_at) AS month, p.category_id,
84
+ COUNT(DISTINCT o.id) AS order_count, SUM(oi.quantity * oi.price) AS revenue
85
+ FROM orders o JOIN order_items oi ON oi.order_id = o.id
86
+ JOIN products p ON p.id = oi.product_id
87
+ GROUP BY month, p.category_id WITH DATA;
88
+
89
+ -- 刷新物化视图
90
+ REFRESH MATERIALIZED VIEW mv_monthly_sales;
91
+
92
+ -- 并发刷新(需唯一索引, PG 9.4+)
93
+ CREATE UNIQUE INDEX idx_mv_monthly_sales_unique ON mv_monthly_sales (month, category_id);
94
+ REFRESH MATERIALIZED VIEW CONCURRENTLY mv_monthly_sales;
95
+ ```
@@ -0,0 +1,133 @@
1
+ # 分区表与 FDW 详解
2
+
3
+ ## 分区表 (PG 10+)
4
+
5
+ ### RANGE 分区
6
+
7
+ ```sql
8
+ CREATE TABLE orders_partitioned (
9
+ id BIGSERIAL, user_id INTEGER NOT NULL, total_amount NUMERIC(12,2),
10
+ status TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
11
+ ) PARTITION BY RANGE (created_at);
12
+
13
+ CREATE TABLE orders_2024_01 PARTITION OF orders_partitioned
14
+ FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
15
+ CREATE TABLE orders_2024_02 PARTITION OF orders_partitioned
16
+ FOR VALUES FROM ('2024-02-01') TO ('2024-03-01');
17
+
18
+ -- 默认分区
19
+ CREATE TABLE orders_default PARTITION OF orders_partitioned DEFAULT;
20
+ ```
21
+
22
+ ### LIST 分区
23
+
24
+ ```sql
25
+ CREATE TABLE customers_partitioned (
26
+ id BIGSERIAL, name TEXT NOT NULL, region TEXT NOT NULL
27
+ ) PARTITION BY LIST (region);
28
+
29
+ CREATE TABLE customers_asia PARTITION OF customers_partitioned
30
+ FOR VALUES IN ('CN', 'JP', 'KR', 'SG');
31
+ CREATE TABLE customers_americas PARTITION OF customers_partitioned
32
+ FOR VALUES IN ('US', 'CA', 'BR', 'MX');
33
+ ```
34
+
35
+ ### HASH 分区
36
+
37
+ ```sql
38
+ CREATE TABLE logs_partitioned (
39
+ id BIGSERIAL, level TEXT, message TEXT, logged_at TIMESTAMPTZ DEFAULT NOW()
40
+ ) PARTITION BY HASH (id);
41
+
42
+ CREATE TABLE logs_p0 PARTITION OF logs_partitioned FOR VALUES WITH (MODULUS 4, REMAINDER 0);
43
+ CREATE TABLE logs_p1 PARTITION OF logs_partitioned FOR VALUES WITH (MODULUS 4, REMAINDER 1);
44
+ CREATE TABLE logs_p2 PARTITION OF logs_partitioned FOR VALUES WITH (MODULUS 4, REMAINDER 2);
45
+ CREATE TABLE logs_p3 PARTITION OF logs_partitioned FOR VALUES WITH (MODULUS 4, REMAINDER 3);
46
+ ```
47
+
48
+ ### 子分区 (PG 11+)
49
+
50
+ ```sql
51
+ CREATE TABLE sales (id BIGSERIAL, sale_date DATE NOT NULL, region TEXT NOT NULL, amount NUMERIC(12,2))
52
+ PARTITION BY RANGE (sale_date);
53
+
54
+ CREATE TABLE sales_2024_q1 PARTITION OF sales
55
+ FOR VALUES FROM ('2024-01-01') TO ('2024-04-01')
56
+ PARTITION BY LIST (region);
57
+ ```
58
+
59
+ ### 分区维护
60
+
61
+ ```sql
62
+ -- 添加新分区
63
+ CREATE TABLE orders_2024_04 PARTITION OF orders_partitioned
64
+ FOR VALUES FROM ('2024-04-01') TO ('2024-05-01');
65
+
66
+ -- 分离分区(变成独立表)
67
+ ALTER TABLE orders_partitioned DETACH PARTITION orders_2024_01;
68
+
69
+ -- 附加分区
70
+ ALTER TABLE orders_partitioned ATTACH PARTITION orders_2024_01
71
+ FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
72
+
73
+ -- 分区裁剪自动生效
74
+ EXPLAIN SELECT * FROM orders_partitioned
75
+ WHERE created_at >= '2024-02-15' AND created_at < '2024-03-01';
76
+ -- 只在 orders_2024_02 分区上扫描
77
+
78
+ -- 分区表索引自动应用到所有分区
79
+ CREATE INDEX ON orders_partitioned (user_id);
80
+ CREATE INDEX ON orders_partitioned (created_at DESC);
81
+ ```
82
+
83
+ ### 分区最佳实践
84
+
85
+ - 每个分区 1-10GB 为宜
86
+ - 时间分区常用:日、周、月、季
87
+ - 定期分离旧分区用于归档
88
+ - 分区数不宜超过 1000
89
+ - 分区键直接影响分区裁剪能力
90
+
91
+ ## FDW (Foreign Data Wrapper)
92
+
93
+ ### postgres_fdw — 跨 PG 数据库
94
+
95
+ ```sql
96
+ CREATE EXTENSION postgres_fdw;
97
+
98
+ CREATE SERVER remote_prod FOREIGN DATA WRAPPER postgres_fdw
99
+ OPTIONS (host '192.168.1.100', port '5432', dbname 'prod_db');
100
+
101
+ CREATE USER MAPPING FOR current_user SERVER remote_prod
102
+ OPTIONS (user 'readonly_user', password 'secret');
103
+
104
+ CREATE FOREIGN TABLE remote_orders (
105
+ id BIGINT, user_id INTEGER, total_amount NUMERIC(12,2), status TEXT, created_at TIMESTAMPTZ
106
+ ) SERVER remote_prod OPTIONS (schema_name 'public', table_name 'orders');
107
+
108
+ -- 查询远程表
109
+ SELECT * FROM remote_orders WHERE created_at > NOW() - INTERVAL '1 hour';
110
+
111
+ -- 批量导入外部表结构
112
+ IMPORT FOREIGN SCHEMA public FROM SERVER remote_prod INTO local_schema
113
+ LIMIT TO (users, orders, products);
114
+ ```
115
+
116
+ ### file_fdw — 读取 CSV
117
+
118
+ ```sql
119
+ CREATE EXTENSION file_fdw;
120
+ CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw;
121
+
122
+ CREATE FOREIGN TABLE csv_orders (
123
+ id BIGINT, user_id INTEGER, amount NUMERIC(10,2), order_date DATE
124
+ ) SERVER file_server OPTIONS (filename '/data/orders.csv', format 'csv', header 'true');
125
+
126
+ SELECT SUM(amount) FROM csv_orders WHERE order_date >= '2024-01-01';
127
+ ```
128
+
129
+ ### FDW 性能考量
130
+
131
+ - 适合小数据量或低频跨库查询
132
+ - 大数据量传输建议用逻辑复制或 ETL
133
+ - WHERE 条件尽量 push down 到远程
@@ -0,0 +1,215 @@
1
+ # 复制/备份/权限详解
2
+
3
+ ## 流复制 (Streaming Replication)
4
+
5
+ ### 主库配置
6
+
7
+ ```conf
8
+ # postgresql.conf
9
+ wal_level = replica
10
+ max_wal_senders = 10
11
+ wal_keep_size = 1GB
12
+ hot_standby = on
13
+ ```
14
+
15
+ ```sql
16
+ -- pg_hba.conf
17
+ -- host replication replicator 192.168.1.0/24 md5
18
+
19
+ CREATE USER replicator WITH REPLICATION LOGIN PASSWORD 'strong_password';
20
+ ```
21
+
22
+ ### 从库搭建
23
+
24
+ ```bash
25
+ # 清空从库数据目录
26
+ rm -rf /var/lib/postgresql/data/*
27
+
28
+ # 从主库拉取基础备份
29
+ pg_basebackup -h 192.168.1.100 -U replicator \
30
+ -D /var/lib/postgresql/data -P -v --wal-method=stream
31
+
32
+ # PG 12+: 创建 standby.signal
33
+ touch /var/lib/postgresql/data/standby.signal
34
+
35
+ # 配置主库连接
36
+ echo "primary_conninfo = 'host=192.168.1.100 port=5432 user=replicator password=strong_password'" \
37
+ >> /var/lib/postgresql/data/postgresql.auto.conf
38
+
39
+ # 启动从库
40
+ systemctl start postgresql
41
+
42
+ # 检查复制状态(主库)
43
+ SELECT * FROM pg_stat_replication;
44
+ # 从库
45
+ SELECT * FROM pg_stat_wal_receiver;
46
+ ```
47
+
48
+ ### 同步 vs 异步
49
+
50
+ ```sql
51
+ -- 同步复制:主库等待从库确认
52
+ -- 配置: synchronous_standby_names = 'FIRST 1 (slave1, slave2)'
53
+ -- 数据零丢失,但写入延迟增加
54
+
55
+ -- 检查同步状态
56
+ SELECT application_name, state, sync_state, write_lag, flush_lag, replay_lag
57
+ FROM pg_stat_replication;
58
+ -- sync: 同步, async: 异步, potential: 候选同步
59
+ ```
60
+
61
+ ## 逻辑复制 (PG 10+)
62
+
63
+ ```sql
64
+ -- 发布端
65
+ CREATE PUBLICATION my_pub FOR ALL TABLES;
66
+ CREATE PUBLICATION orders_pub FOR TABLE orders, order_items;
67
+ CREATE PUBLICATION paid_orders_pub FOR TABLE orders WHERE (status = 'paid'); -- PG 15+
68
+
69
+ -- 订阅端
70
+ CREATE SUBSCRIPTION my_sub
71
+ CONNECTION 'host=192.168.1.100 port=5432 dbname=mydb user=replicator password=strong_password'
72
+ PUBLICATION my_pub;
73
+
74
+ -- 管理
75
+ ALTER SUBSCRIPTION my_sub ENABLE;
76
+ ALTER SUBSCRIPTION my_sub DISABLE;
77
+ ALTER SUBSCRIPTION my_sub REFRESH PUBLICATION;
78
+ DROP SUBSCRIPTION my_sub;
79
+
80
+ -- 监控
81
+ SELECT * FROM pg_stat_subscription;
82
+ ```
83
+
84
+ ## 备份与恢复
85
+
86
+ ### pg_dump — 逻辑备份
87
+
88
+ ```bash
89
+ # SQL 格式
90
+ pg_dump -h localhost -U postgres -d mydb > mydb.sql
91
+
92
+ # 自定义格式(推荐)
93
+ pg_dump -h localhost -U postgres -d mydb -Fc -f mydb.dump
94
+
95
+ # 并行导出目录格式
96
+ pg_dump -h localhost -U postgres -d mydb -Fd -j 4 -f /backup/mydb/
97
+
98
+ # 只导出结构
99
+ pg_dump -h localhost -U postgres -d mydb -s -f mydb_schema.sql
100
+
101
+ # 指定表
102
+ pg_dump -h localhost -U postgres -d mydb -t orders -t users -f mydb_tables.sql
103
+
104
+ # 全局对象(角色、表空间)
105
+ pg_dumpall -h localhost -U postgres -g -f global_objects.sql
106
+ ```
107
+
108
+ ### pg_restore — 恢复
109
+
110
+ ```bash
111
+ pg_restore -h localhost -U postgres -d mydb /backup/mydb.dump
112
+ pg_restore -h localhost -U postgres -d mydb -j 4 /backup/mydb.dump # 并行
113
+ pg_restore -h localhost -U postgres -d mydb -t users /backup/mydb.dump # 指定表
114
+
115
+ # SQL 文件恢复
116
+ psql -h localhost -U postgres -d mydb < mydb.sql
117
+ ```
118
+
119
+ ### WAL 归档与 PITR
120
+
121
+ ```conf
122
+ # postgresql.conf
123
+ archive_mode = on
124
+ archive_command = 'cp %p /archive/%f'
125
+ wal_keep_size = 1GB
126
+ ```
127
+
128
+ ```bash
129
+ # 创建基础备份
130
+ pg_basebackup -h localhost -U postgres -D /backup/base -P -v --wal-method=stream
131
+
132
+ # PITR 恢复步骤:
133
+ # 1. 停止 PG
134
+ # 2. 用基础备份恢复数据目录
135
+ # 3. 创建 recovery.signal (PG 12+)
136
+ # 4. 配置 restore_command 和 recovery_target_time
137
+ # 5. 启动 PG
138
+ ```
139
+
140
+ ### pg_basebackup — 物理备份
141
+
142
+ ```bash
143
+ # 基础用法
144
+ pg_basebackup -h localhost -U replicator -D /backup/pg_base -P -v --wal-method=stream
145
+
146
+ # 压缩 tar 格式
147
+ pg_basebackup -h localhost -U replicator -D /backup/pg_base -Ft -z -P -v
148
+
149
+ # 验证备份 (PG 13+)
150
+ pg_verifybackup /backup/pg_base
151
+ ```
152
+
153
+ ## 高可用工具
154
+
155
+ ```bash
156
+ # Patroni (基于 etcd/consul/ZK)
157
+ # 自动故障转移 + 自动恢复
158
+ patroni /etc/patroni/patroni.yml
159
+
160
+ # repmgr
161
+ repmgr -f /etc/repmgr.conf primary register
162
+ repmgr -f /etc/repmgr.conf standby clone
163
+ repmgr -f /etc/repmgr.conf standby register
164
+ repmgr -f /etc/repmgr.conf standby switchover
165
+
166
+ # PgBouncer — 连接池
167
+ # Pgpool-II — 连接池 + 读写分离 + 负载均衡
168
+ ```
169
+
170
+ ## 权限管理
171
+
172
+ ```sql
173
+ -- ROLE 管理
174
+ CREATE ROLE app_user WITH LOGIN PASSWORD 'password';
175
+ CREATE ROLE readonly_role;
176
+ CREATE ROLE readwrite_role;
177
+
178
+ -- 角色层级
179
+ GRANT readonly_role TO app_user;
180
+
181
+ -- Schema 权限
182
+ GRANT USAGE ON SCHEMA public TO readonly_role;
183
+ GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_role;
184
+ GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO readwrite_role;
185
+
186
+ -- 默认权限(未来新建表自动授权)
187
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly_role;
188
+
189
+ -- 序列、函数
190
+ GRANT USAGE, SELECT ON ALL SEQUENCES TO readwrite_role;
191
+ GRANT EXECUTE ON ALL FUNCTIONS TO readwrite_role;
192
+
193
+ -- RLS 行级安全(多租户隔离)
194
+ CREATE TABLE tenant_orders (id BIGSERIAL PRIMARY KEY, tenant_id INTEGER NOT NULL, ...);
195
+ ALTER TABLE tenant_orders ENABLE ROW LEVEL SECURITY;
196
+
197
+ CREATE POLICY tenant_isolation ON tenant_orders
198
+ USING (tenant_id = current_setting('app.tenant_id')::INTEGER);
199
+
200
+ ALTER TABLE tenant_orders FORCE ROW LEVEL SECURITY;
201
+ SET app.tenant_id = '1001'; -- 应用层设置
202
+ ```
203
+
204
+ ## 扩展
205
+
206
+ ```sql
207
+ -- PostGIS: CREATE EXTENSION postgis;
208
+ -- pgvector: CREATE EXTENSION vector;
209
+ -- pg_stat_statements: CREATE EXTENSION pg_stat_statements;
210
+ -- uuid-ossp: CREATE EXTENSION "uuid-ossp";
211
+ -- pgcrypto: CREATE EXTENSION pgcrypto;
212
+ -- citext: CREATE EXTENSION citext;
213
+ -- pg_trgm: CREATE EXTENSION pg_trgm;
214
+ -- unaccent: CREATE EXTENSION unaccent;
215
+ ```