sql
此内容尚不支持你的语言。
install
Section titled “install”Arch\Garuda
Section titled “Arch\Garuda”# https://archlinux.org/packages/?sort=&q=postgresql&maintainer=&flagged=sudo pacman -S postgresql# 初始化数据库# 确保目录权限正确sudo chown postgres:postgres /var/lib/postgres/datasudo chmod 700 /var/lib/postgres/data# 切换到 postgres 用户并初始化sudo -iu postgres # -i: 模拟登录(创建完整的登录环境,加载用户的环境变量); -u postgres: 切换到 postgres 用户身份initdb --locale=C -E UTF8 -D /var/lib/postgres/data # --locale=C: 设置数据库的区域设置为 C(POSIX 标准),这是最通用的设置; -E UTF8: 设置数据库的默认字符编码为 UTF-8,支持多语言字符; -D /var/lib/postgres/data: 指定数据库文件存储目录# 成功后会显示:成功。你现在可以用下面的命令开启数据库服务器: pg_ctl -D /var/lib/postgres/data -l logfile startexit # 退出 postgres 用户# 启动服务sudo systemctl start postgresql # 启动 PostgreSQL 服务sudo systemctl enable postgresql # 设置 PostgreSQL 服务开机自启Debian\Ubuntu
Section titled “Debian\Ubuntu”sudo apt updatesudo apt install postgresql# 启动服务sudo systemctl start postgresqlsudo systemctl enable postgresqlWindows
Section titled “Windows”默认自带用户 postgres
# 使用 postgres 超级用户创建一个名为 "aa" 的用户,并赋予其创建数据库、角色和超级用户权限sudo -u postgres createuser -d -r -s aa# 创建用户并设置密码sudo -u postgres psql -c "CREATE USER myuser WITH PASSWORD 'mypassword';"# 或修改已有用户密码sudo -u postgres psql -c "ALTER USER myuser WITH PASSWORD 'mypassword';"create
Section titled “create”# 创建数据库 (使用 createdb 工具,推荐)## 以 postgres 用户身份运行sudo -u postgres createdb mcc # postgresql://postgres@localhost:5432/mccsudo -u postgres createdb -O labrinth labrinth # postgresql://labrinth:labrinth@localhost/labrinth# 验证psql -U labrinth -d labrinth -h localhost -W
# 连接到指定数据库sudo -u postgres psql -d mccdelete
Section titled “delete”sudo -u postgres dropdb labrinthmigration
Section titled “migration”for f in $(ls migrations/*.sql | sort); do psql -U labrinth -d labrinth -f "$f"donetext -> text 1 (text[])
Section titled “text -> text 1 (text[])”-- 1. 去掉旧的默认值ALTER TABLE "project_member"ALTER COLUMN "permissions" DROP DEFAULT;
-- 2. 修改类型,并把已有数据转换为数组ALTER TABLE "project_member"ALTER COLUMN "permissions" SET DATA TYPE text[]USING CASE WHEN permissions = '[]' THEN '{}'::text[] -- 把 '[]' 映射为空数组 ELSE (SELECT jsonb_array_elements_text(permissions::jsonb)) -- '["read","write"]' -> ["read","write"]END;
-- 3. 设置新的默认值为空数组ALTER TABLE "project_member"ALTER COLUMN "permissions" SET DEFAULT '{}'::text[];jsonb -> text[]
Section titled “jsonb -> text[]”-- 1. 删除默认值ALTER TABLE projectALTER COLUMN game_versions DROP DEFAULT;-- 2. 创建转换函数CREATE OR REPLACE FUNCTION jsonb_to_text_array(input jsonb) RETURNS text[] AS $$BEGIN -- 如果是空 jsonb 数组,返回空 text[];否则展开聚合成 text[] IF input = '[]'::jsonb OR input IS NULL THEN RETURN '{}'::text[]; ELSE RETURN ARRAY(SELECT jsonb_array_elements_text(input)); END IF;END;$$ LANGUAGE plpgsql IMMUTABLE;-- 3. 修改列类型并转换已有数据ALTER TABLE projectALTER COLUMN game_versionsSET DATA TYPE text[]USING jsonb_to_text_array(game_versions);-- 4. 添加默认值ALTER TABLE projectALTER COLUMN game_versionsSET DEFAULT '{}'::text[];PostgreSQL ID 类型
Section titled “PostgreSQL ID 类型”1. 自增ID类型
Section titled “1. 自增ID类型”SERIAL (PostgreSQL 传统方式)
Section titled “SERIAL (PostgreSQL 传统方式)”-- SERIAL 实际上是 INTEGER + DEFAULT nextval('sequence_name')CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(100));
-- 等价于:CREATE SEQUENCE users_id_seq;CREATE TABLE users ( id INTEGER NOT NULL DEFAULT nextval('users_id_seq') PRIMARY KEY, name VARCHAR(100));BIGSERIAL (大整数自增)
Section titled “BIGSERIAL (大整数自增)”CREATE TABLE logs ( id BIGSERIAL PRIMARY KEY, -- 支持更大范围的ID message TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);SMALLSERIAL (小整数自增)
Section titled “SMALLSERIAL (小整数自增)”CREATE TABLE categories ( id SMALLSERIAL PRIMARY KEY, -- 适用于较小的表 name VARCHAR(50));2. IDENTITY 列 (SQL 标准方式,推荐)
Section titled “2. IDENTITY 列 (SQL 标准方式,推荐)”GENERATED ALWAYS AS IDENTITY
Section titled “GENERATED ALWAYS AS IDENTITY”CREATE TABLE products ( id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name VARCHAR(100), price DECIMAL(10,2));
-- 插入时不能指定 id 值INSERT INTO products (name, price) VALUES ('iPhone', 999.99);GENERATED BY DEFAULT AS IDENTITY
Section titled “GENERATED BY DEFAULT AS IDENTITY”CREATE TABLE orders ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, customer_id INTEGER, total DECIMAL(10,2));
-- 可以手动指定 id 值,也可以让系统自动生成INSERT INTO orders (customer_id, total) VALUES (1, 100.00); -- 自动生成 idINSERT INTO orders (id, customer_id, total) VALUES (1000, 2, 200.00); -- 手动指定 id3. UUID 类型
Section titled “3. UUID 类型”安装 UUID 扩展
Section titled “安装 UUID 扩展”CREATE EXTENSION IF NOT EXISTS "uuid-ossp";-- 或者使用内置函数 (PostgreSQL 13+)CREATE EXTENSION IF NOT EXISTS "pgcrypto";UUID 作为主键
Section titled “UUID 作为主键”CREATE TABLE sessions ( id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, -- 或使用内置函数 (PostgreSQL 13+) -- id UUID DEFAULT gen_random_uuid() PRIMARY KEY, user_id INTEGER, token VARCHAR(255), expires_at TIMESTAMP);UUID 的优势
Section titled “UUID 的优势”- 全局唯一,适合分布式系统
- 不会泄露表的记录数量
- 更好的安全性
4. NanoID 类型(推荐的现代替代方案)
Section titled “4. NanoID 类型(推荐的现代替代方案)”NanoID 简介
Section titled “NanoID 简介”NanoID 是一个小巧、安全、URL友好的唯一ID生成器,由 Andrey Sitnik 开发,是 UUID 的现代替代方案。
NanoID 的优势
Section titled “NanoID 的优势”- 更小的体积: 默认21个字符,比UUID的36个字符更紧凑
- URL友好: 不包含特殊字符,可直接用于URL
- 更高性能: 生成速度比UUID快60%
- 可定制: 可自定义长度和字符集
- 更安全: 使用更好的随机数生成算法
- 无冲突: 即使每秒生成1000个ID,需要1千年才可能出现重复
在 PostgreSQL 中使用 NanoID
Section titled “在 PostgreSQL 中使用 NanoID”方法1: 使用 nanoid 扩展
Section titled “方法1: 使用 nanoid 扩展”-- 安装 nanoid 扩展 (需要先从源码编译安装)CREATE EXTENSION IF NOT EXISTS nanoid;
-- 创建表使用 nanoidCREATE TABLE posts ( id TEXT DEFAULT nanoid() PRIMARY KEY, title VARCHAR(255), content TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
-- 自定义长度的 nanoidCREATE TABLE short_urls ( id TEXT DEFAULT nanoid(10) PRIMARY KEY, -- 10个字符长度 original_url TEXT, clicks INTEGER DEFAULT 0);方法2: 应用层生成 (推荐)
Section titled “方法2: 应用层生成 (推荐)”-- 在应用层生成 NanoID,数据库只存储CREATE TABLE articles ( id TEXT PRIMARY KEY, -- 应用层生成的 nanoid title VARCHAR(255), content TEXT, author_id TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
-- 插入数据 (ID 由应用层生成)-- JavaScript: import { nanoid } from 'nanoid'-- Python: from nanoid import generate-- 然后插入: INSERT INTO articles (id, title, content) VALUES ('V1StGXR8_Z5jdHi6B-myT', 'My Article', 'Content...');方法3: 使用 PL/pgSQL 函数
Section titled “方法3: 使用 PL/pgSQL 函数”-- 创建简单的 nanoid 生成函数CREATE OR REPLACE FUNCTION generate_nanoid(size integer DEFAULT 21)RETURNS textLANGUAGE plpgsqlAS $$DECLARE alphabet text := '_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; id text := ''; i integer;BEGIN FOR i IN 1..size LOOP id := id || substr(alphabet, floor(random() * length(alphabet) + 1)::integer, 1); END LOOP; RETURN id;END;$$;
-- 使用自定义函数CREATE TABLE users ( id TEXT DEFAULT generate_nanoid() PRIMARY KEY, email VARCHAR(255) UNIQUE, username VARCHAR(100), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);NanoID vs UUID 对比
Section titled “NanoID vs UUID 对比”| 特性 | NanoID | UUID |
|---|---|---|
| 长度 | 21字符 | 36字符 |
| URL友好 | ✅ | ❌ (包含-) |
| 性能 | 更快 | 较慢 |
| 数据库支持 | 需要扩展/函数 | 原生支持 |
| 碰撞概率 | 极低 | 极低 |
| 人类可读性 | 更好 | 较差 |
不同语言中的 NanoID
Section titled “不同语言中的 NanoID”JavaScript/TypeScript
Section titled “JavaScript/TypeScript”import { nanoid } from 'nanoid';
const id = nanoid(); // "V1StGXR8_Z5jdHi6B-myT"const shortId = nanoid(10); // "IRFa-VaY2b"
// 自定义字符集import { customAlphabet } from 'nanoid';const nanoid = customAlphabet('1234567890abcdef', 10);const id = nanoid(); // "4f90d13a42"Python
Section titled “Python”from nanoid import generate
id = generate() # "V1StGXR8_Z5jdHi6B-myT"short_id = generate(size=10) # "IRFa-VaY2b"
# 自定义字符集from nanoid import generateid = generate(alphabet='1234567890abcdef', size=10) # "4f90d13a42"use Hidehalo\Nanoid\Client;
$client = new Client();$id = $client->generateId(); // "V1StGXR8_Z5jdHi6B-myT"$shortId = $client->generateId(10); // "IRFa-VaY2b"-- 1. 为 API 资源使用 NanoIDCREATE TABLE api_keys ( id TEXT DEFAULT generate_nanoid() PRIMARY KEY, user_id INTEGER REFERENCES users(id), name VARCHAR(100), key_hash TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
-- 2. 为短链接服务使用短 NanoIDCREATE TABLE short_links ( id TEXT DEFAULT generate_nanoid(8) PRIMARY KEY, original_url TEXT NOT NULL, clicks INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
-- 3. 为会话使用 NanoIDCREATE TABLE user_sessions ( id TEXT DEFAULT generate_nanoid() PRIMARY KEY, user_id INTEGER REFERENCES users(id), ip_address INET, user_agent TEXT, expires_at TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
-- 4. 索引优化CREATE INDEX idx_posts_id_hash ON posts USING hash(id);CREATE INDEX idx_articles_author_id ON articles(author_id);何时选择 NanoID
Section titled “何时选择 NanoID”选择 NanoID 当:
- 需要URL友好的ID
- 希望更短的ID长度
- 性能要求较高
- 构建现代Web应用
- 需要在前端生成ID
选择 UUID 当:
- 需要数据库原生支持
- 与老系统集成
- 需要标准化的解决方案
- 团队更熟悉UUID
5. Drizzle ORM 中的 ID 使用
Section titled “5. Drizzle ORM 中的 ID 使用”Drizzle 中的各种 ID 类型
Section titled “Drizzle 中的各种 ID 类型”import { pgTable, serial, bigserial, text, timestamp } from 'drizzle-orm/pg-core';
// 使用 serialexport const users = pgTable('users', { id: serial('id').primaryKey(), email: text('email').notNull().unique(), name: text('name'), createdAt: timestamp('created_at').defaultNow(),});
// 使用 bigserialexport const logs = pgTable('logs', { id: bigserial('id', { mode: 'number' }).primaryKey(), // mode: 'number' | 'bigint' message: text('message'), createdAt: timestamp('created_at').defaultNow(),});UUID 在 Drizzle 中
Section titled “UUID 在 Drizzle 中”import { pgTable, uuid, text, timestamp } from 'drizzle-orm/pg-core';import { sql } from 'drizzle-orm';
// 使用 UUIDexport const sessions = pgTable('sessions', { id: uuid('id').default(sql`gen_random_uuid()`).primaryKey(), userId: uuid('user_id').notNull(), token: text('token'), expiresAt: timestamp('expires_at'),});
// 或者在应用层生成export const posts = pgTable('posts', { id: uuid('id').primaryKey(), // 应用层生成 title: text('title').notNull(), content: text('content'), authorId: uuid('author_id').notNull(),});NanoID 在 Drizzle 中
Section titled “NanoID 在 Drizzle 中”import { pgTable, text, timestamp, varchar } from 'drizzle-orm/pg-core';import { nanoid } from 'nanoid';
// 应用层生成 NanoID (推荐方式)export const articles = pgTable('articles', { id: text('id').primaryKey().$defaultFn(() => nanoid()), slug: varchar('slug', { length: 255 }).unique(), title: text('title').notNull(), content: text('content'), createdAt: timestamp('created_at').defaultNow(),});
// 短 ID 用于短链接export const shortUrls = pgTable('short_urls', { id: text('id').primaryKey().$defaultFn(() => nanoid(8)), originalUrl: text('original_url').notNull(), clicks: serial('clicks').default(0),});
// 自定义字符集的 NanoIDimport { customAlphabet } from 'nanoid';const nanoidCustom = customAlphabet('1234567890abcdef', 10);
export const apiKeys = pgTable('api_keys', { id: text('id').primaryKey().$defaultFn(() => nanoidCustom()), userId: serial('user_id').notNull(), name: text('name'), keyHash: text('key_hash'),});CUID2 在 Drizzle 中 (另一个现代选择)
Section titled “CUID2 在 Drizzle 中 (另一个现代选择)”import { createId } from '@paralleldrive/cuid2';
export const orders = pgTable('orders', { id: text('id').primaryKey().$defaultFn(() => createId()), customerId: text('customer_id').notNull(), total: decimal('total', { precision: 10, scale: 2 }), status: text('status').default('pending'),});Drizzle 查询示例
Section titled “Drizzle 查询示例”import { db } from './db';import { users, posts } from './schema';import { eq } from 'drizzle-orm';
// 插入用户 (自动生成 serial ID)const newUser = await db.insert(users).values({ email: 'user@example.com', name: 'John Doe',}).returning();
// 插入文章 (自动生成 NanoID)const newPost = await db.insert(posts).values({ title: 'My Article', content: 'Article content...', authorId: newUser[0].id,}).returning();
// 查询const userPosts = await db .select() .from(posts) .where(eq(posts.authorId, newUser[0].id));6. PostgreSQL UUID 优化深度分析
Section titled “6. PostgreSQL UUID 优化深度分析”PostgreSQL 对 UUID 的原生优化
Section titled “PostgreSQL 对 UUID 的原生优化”-- UUID 在 PostgreSQL 中的存储-- UUID 类型:16字节二进制存储 (比 TEXT 的 36字节更高效)CREATE TABLE uuid_test ( id UUID PRIMARY KEY, data TEXT);
-- 对比 TEXT 存储CREATE TABLE text_test ( id TEXT PRIMARY KEY, -- 36字节 + 变长开销 data TEXT);
-- 查看存储大小SELECT pg_size_pretty(pg_total_relation_size('uuid_test')) as uuid_size, pg_size_pretty(pg_total_relation_size('text_test')) as text_size;-- UUID 的 B-tree 索引性能CREATE INDEX idx_uuid_btree ON uuid_test(id);
-- Hash 索引更适合等值查询CREATE INDEX idx_uuid_hash ON uuid_test USING hash(id);
-- 部分索引优化CREATE INDEX idx_recent_uuid ON uuid_test(id)WHERE created_at > (CURRENT_DATE - INTERVAL '30 days');UUID 生成函数性能对比
Section titled “UUID 生成函数性能对比”-- 性能测试脚本DO $$DECLARE start_time TIMESTAMP; end_time TIMESTAMP; i INTEGER;BEGIN -- 测试 gen_random_uuid() start_time := clock_timestamp(); FOR i IN 1..100000 LOOP PERFORM gen_random_uuid(); END LOOP; end_time := clock_timestamp(); RAISE NOTICE 'gen_random_uuid: %', end_time - start_time;
-- 测试 uuid_generate_v4() (需要 uuid-ossp 扩展) start_time := clock_timestamp(); FOR i IN 1..100000 LOOP PERFORM uuid_generate_v4(); END LOOP; end_time := clock_timestamp(); RAISE NOTICE 'uuid_generate_v4: %', end_time - start_time;END $$;NanoID vs UUID 深度对比
Section titled “NanoID vs UUID 深度对比”存储空间对比
Section titled “存储空间对比”-- 实际存储空间测试CREATE TABLE storage_test ( uuid_col UUID, nanoid_col TEXT, data TEXT);
-- 插入测试数据INSERT INTO storage_testSELECT gen_random_uuid(), substr(md5(random()::text), 1, 21), -- 模拟 21字符 nanoid 'test data'FROM generate_series(1, 1000000);
-- 查看存储空间SELECT pg_size_pretty(pg_column_size(uuid_col)) as uuid_size, pg_size_pretty(pg_column_size(nanoid_col)) as nanoid_size, pg_size_pretty(pg_total_relation_size('storage_test')) as total_sizeFROM storage_test LIMIT 1;索引性能对比
Section titled “索引性能对比”-- 创建索引CREATE INDEX idx_uuid ON storage_test(uuid_col);CREATE INDEX idx_nanoid ON storage_test(nanoid_col);
-- 查看索引大小SELECT indexname, pg_size_pretty(pg_relation_size(indexname::regclass)) as index_sizeFROM pg_indexesWHERE tablename = 'storage_test';
-- 查询性能测试EXPLAIN (ANALYZE, BUFFERS)SELECT * FROM storage_test WHERE uuid_col = gen_random_uuid();
EXPLAIN (ANALYZE, BUFFERS)SELECT * FROM storage_test WHERE nanoid_col = 'some_nanoid_value_here';真实性能对比结果
Section titled “真实性能对比结果”PostgreSQL 中的实际表现
Section titled “PostgreSQL 中的实际表现”| 特性 | UUID | NanoID (TEXT) | 赢家 |
|---|---|---|---|
| 存储空间 | 16字节 | 21字节 + 开销 (~25字节) | 🏆 UUID |
| 索引大小 | 更小 | 更大 | 🏆 UUID |
| B-tree 查询 | 优化的二进制比较 | 字符串比较 | 🏆 UUID |
| Hash 索引 | 原生支持 | 文本hash | 🏆 UUID |
| 生成性能 | 数据库原生 | 应用层生成 | 🏆 UUID |
| 网络传输 | 36字符 | 21字符 | 🏆 NanoID |
| URL友好 | 包含-字符 | 完全友好 | 🏆 NanoID |
| 人类可读 | 较差 | 更好 | 🏆 NanoID |
选择 UUID 当:
Section titled “选择 UUID 当:”// 高性能数据库密集型应用export const highVolumeTable = pgTable('transactions', { id: uuid('id').default(sql`gen_random_uuid()`).primaryKey(), amount: decimal('amount', { precision: 15, scale: 2 }), userId: uuid('user_id').notNull(), createdAt: timestamp('created_at').defaultNow(),});
// 需要数据库层面的引用完整性export const users = pgTable('users', { id: uuid('id').default(sql`gen_random_uuid()`).primaryKey(), email: text('email').unique(),});
export const userProfiles = pgTable('user_profiles', { id: uuid('id').default(sql`gen_random_uuid()`).primaryKey(), userId: uuid('user_id').notNull().references(() => users.id), bio: text('bio'),});选择 NanoID 当:
Section titled “选择 NanoID 当:”// API 资源,需要URL友好export const blogPosts = pgTable('blog_posts', { id: text('id').primaryKey().$defaultFn(() => nanoid()), slug: text('slug').unique(), title: text('title').notNull(),});
// 短链接服务export const shortLinks = pgTable('short_links', { id: text('id').primaryKey().$defaultFn(() => nanoid(8)), url: text('url').notNull(),});
// 需要在前端生成ID的场景export const clientGenerated = pgTable('uploads', { id: text('id').primaryKey(), // 前端生成 nanoid filename: text('filename'), uploadedAt: timestamp('uploaded_at').defaultNow(),});混合策略 (推荐)
Section titled “混合策略 (推荐)”// 内部关系使用 UUID (性能优先)export const users = pgTable('users', { id: uuid('id').default(sql`gen_random_uuid()`).primaryKey(), email: text('email').unique(), publicId: text('public_id').$defaultFn(() => nanoid()), // 对外暴露的ID});
export const posts = pgTable('posts', { id: uuid('id').default(sql`gen_random_uuid()`).primaryKey(), publicId: text('public_id').$defaultFn(() => nanoid()), authorId: uuid('author_id').notNull().references(() => users.id), title: text('title'),});
// API 路由使用 publicId,数据库查询使用内部 UUID// GET /api/posts/V1StGXR8_Z5jdHi6B-myT7. 内置ID和系统列
Section titled “7. 内置ID和系统列”OID (Object Identifier)
Section titled “OID (Object Identifier)”-- 创建带 OID 的表 (不推荐,已废弃)CREATE TABLE old_table ( name VARCHAR(100)) WITH OIDS;
-- 查询 OIDSELECT oid, * FROM old_table;-- ctid: 物理位置标识符SELECT ctid, * FROM users;
-- xmin, xmax: 事务IDSELECT xmin, xmax, * FROM users;
-- tableoid: 表的OIDSELECT tableoid, * FROM users;8. 自定义序列
Section titled “8. 自定义序列”创建自定义序列
Section titled “创建自定义序列”-- 创建序列CREATE SEQUENCE custom_id_seq START WITH 1000 INCREMENT BY 1 MINVALUE 1000 MAXVALUE 999999999 CACHE 1;
-- 使用序列CREATE TABLE custom_table ( id INTEGER DEFAULT nextval('custom_id_seq') PRIMARY KEY, data TEXT);
-- 序列操作SELECT nextval('custom_id_seq'); -- 获取下一个值SELECT currval('custom_id_seq'); -- 获取当前值SELECT setval('custom_id_seq', 5000); -- 设置序列值9. 复合主键
Section titled “9. 复合主键”CREATE TABLE order_items ( order_id INTEGER, product_id INTEGER, quantity INTEGER, price DECIMAL(10,2), PRIMARY KEY (order_id, product_id));10. 最佳实践
Section titled “10. 最佳实践”选择合适的ID类型
Section titled “选择合适的ID类型”-- 小表使用 SMALLSERIAL 或 SMALLINT IDENTITYCREATE TABLE status ( id SMALLINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name VARCHAR(20));
-- 中等表使用 INTEGER IDENTITYCREATE TABLE users ( id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, email VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
-- 大表或需要全局唯一使用 BIGINT IDENTITY 或 UUIDCREATE TABLE events ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, -- 或 -- id UUID DEFAULT gen_random_uuid() PRIMARY KEY, event_type VARCHAR(50), data JSONB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);-- 为外键创建索引CREATE INDEX idx_orders_customer_id ON orders(customer_id);
-- UUID 索引优化CREATE INDEX idx_sessions_id_hash ON sessions USING hash(id);11. 查询ID信息
Section titled “11. 查询ID信息”查看序列信息
Section titled “查看序列信息”-- 查看所有序列SELECT * FROM information_schema.sequences;
-- 查看特定序列的详细信息SELECT * FROM pg_sequences WHERE schemaname = 'public';
-- 查看序列当前值SELECT sequence_name, last_value, increment_byFROM information_schema.sequences sJOIN pg_sequences ps ON s.sequence_name = ps.sequencename;查看表的ID列信息
Section titled “查看表的ID列信息”-- 查看表的IDENTITY列SELECT table_name, column_name, is_identity, identity_generationFROM information_schema.columnsWHERE is_identity = 'YES'AND table_schema = 'public';
-- 查看表的默认值SELECT table_name, column_name, column_defaultFROM information_schema.columnsWHERE column_default IS NOT NULLAND table_schema = 'public'ORDER BY table_name, ordinal_position;