EightSixNineEightSixNine
Linux2025年12月25日by admin👁️ 41

PostgreSQL 安装配置与常用命令指南

PostgreSQL 是功能强大的开源关系型数据库,以稳定性和标准兼容性著称。

Windows 安装

下载安装包

从官网下载安装程序:https://www.postgresql.org/download/windows/

推荐使用 EDB 提供的安装包,包含:

  • PostgreSQL Server
  • pgAdmin 4(图形管理工具)
  • Stack Builder(扩展安装工具)
  • 命令行工具

安装步骤

  1. 运行安装程序,选择安装目录(默认 C:\Program Files\PostgreSQL\16
  2. 选择组件(建议全选)
  3. 设置数据目录(默认 C:\Program Files\PostgreSQL\16\data
  4. 设置 postgres 超级用户密码(务必记住)
  5. 设置端口(默认 5432)
  6. 选择区域设置(建议选择 Chinese, China 或 Default locale)
  7. 完成安装

配置环境变量

# 添加到系统 PATH(以管理员身份运行 PowerShell)
$pgPath = "C:\Program Files\PostgreSQL\16\bin"
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";$pgPath", "Machine")

# 或手动添加
# 系统属性 -> 高级 -> 环境变量 -> Path -> 添加 PostgreSQL bin 目录

验证安装

# 命令提示符
psql --version
psql -U postgres

Windows 服务管理

# 查看服务状态
sc query postgresql-x64-16

# 启动服务
net start postgresql-x64-16

# 停止服务
net stop postgresql-x64-16

# 重启服务
net stop postgresql-x64-16 & net start postgresql-x64-16
# PowerShell 方式
Get-Service -Name "postgresql*"
Start-Service -Name "postgresql-x64-16"
Stop-Service -Name "postgresql-x64-16"
Restart-Service -Name "postgresql-x64-16"

使用 Chocolatey 安装

# 安装 Chocolatey(如未安装)
Set-ExecutionPolicy Bypass -Scope Process -Force
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

# 安装 PostgreSQL
choco install postgresql16 -y

# 安装后设置密码
psql -U postgres
\password postgres

使用 Scoop 安装

# 添加 extras bucket
scoop bucket add extras

# 安装 PostgreSQL
scoop install postgresql

# 初始化数据库
initdb -U postgres -A password -E utf8 -W -D $env:USERPROFILE\scoop\apps\postgresql\current\data

# 启动服务
pg_ctl -D $env:USERPROFILE\scoop\apps\postgresql\current\data -l logfile start

Linux 安装

Ubuntu/Debian

sudo apt update
sudo apt install postgresql postgresql-contrib

# 启动服务
sudo systemctl start postgresql
sudo systemctl enable postgresql

# 查看状态
sudo systemctl status postgresql

使用官方仓库(获取最新版本)

# 添加 PostgreSQL 官方仓库
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

# 导入仓库签名密钥
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

# 更新并安装
sudo apt update
sudo apt install postgresql-16 postgresql-contrib-16

CentOS/RHEL/Rocky Linux

# 安装仓库
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

# 禁用内置模块
sudo dnf -qy module disable postgresql

# 安装 PostgreSQL 16
sudo dnf install -y postgresql16-server postgresql16-contrib

# 初始化数据库
sudo /usr/pgsql-16/bin/postgresql-16-setup initdb

# 启动服务
sudo systemctl start postgresql-16
sudo systemctl enable postgresql-16

Arch Linux

sudo pacman -S postgresql

# 切换到 postgres 用户初始化
sudo -iu postgres
initdb -D /var/lib/postgres/data

# 启动服务
sudo systemctl start postgresql
sudo systemctl enable postgresql

Docker

docker run -d \
  --name postgres \
  -p 5432:5432 \
  -e POSTGRES_USER=admin \
  -e POSTGRES_PASSWORD=password \
  -e POSTGRES_DB=mydb \
  -v pgdata:/var/lib/postgresql/data \
  postgres:16

Docker Compose

# docker-compose.yml
version: '3.8'
services:
  postgres:
    image: postgres:16
    container_name: postgres
    restart: unless-stopped
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydb
      TZ: Asia/Shanghai
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql  # 初始化脚本
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin -d mydb"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  pgdata:

初始配置

设置 postgres 用户密码

# Linux - 切换到 postgres 用户
sudo -u postgres psql

# 设置密码
\password postgres
# 或
ALTER USER postgres WITH PASSWORD 'your_secure_password';

创建新用户和数据库

-- 创建用户
CREATE USER myuser WITH PASSWORD 'mypassword';

-- 创建数据库并指定所有者
CREATE DATABASE mydb OWNER myuser;

-- 授予权限
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;

-- 连接到数据库后授予 schema 权限
\c mydb
GRANT ALL ON SCHEMA public TO myuser;

允许远程连接

编辑 postgresql.conf

# 查找配置文件位置
sudo -u postgres psql -c "SHOW config_file;"

# Linux 通常在
# /etc/postgresql/16/main/postgresql.conf
# /var/lib/pgsql/16/data/postgresql.conf

# Windows 通常在
# C:\Program Files\PostgreSQL\16\data\postgresql.conf

修改监听地址:

# postgresql.conf
listen_addresses = '*'          # 监听所有地址
# listen_addresses = '0.0.0.0'  # 仅 IPv4
port = 5432

编辑 pg_hba.conf 添加访问规则:

# 查找文件位置
sudo -u postgres psql -c "SHOW hba_file;"
# pg_hba.conf
# TYPE  DATABASE  USER      ADDRESS         METHOD
local   all       all                       peer
host    all       all       127.0.0.1/32    md5
host    all       all       ::1/128         md5
host    all       all       0.0.0.0/0       md5      # 允许所有 IPv4
host    all       all       ::/0            md5      # 允许所有 IPv6
host    mydb      myuser    192.168.1.0/24  md5      # 仅允许特定网段

重载配置:

# Linux
sudo systemctl reload postgresql

# 或在 psql 中
SELECT pg_reload_conf();

防火墙设置

# Ubuntu/Debian (ufw)
sudo ufw allow 5432/tcp

# CentOS/RHEL (firewalld)
sudo firewall-cmd --permanent --add-port=5432/tcp
sudo firewall-cmd --reload

# Windows 防火墙(管理员 PowerShell)
New-NetFirewallRule -DisplayName "PostgreSQL" -Direction Inbound -Protocol TCP -LocalPort 5432 -Action Allow

连接数据库

# 切换到 postgres 用户
sudo -u postgres psql

# 连接指定数据库
psql -U username -d database -h hostname -p 5432

# 使用连接字符串
psql "postgresql://user:password@localhost:5432/database"

psql 命令

-- 常用元命令
\l              -- 列出数据库
\c dbname       -- 切换数据库
\dt             -- 列出表
\d tablename    -- 查看表结构
\du             -- 列出用户
\df             -- 列出函数
\di             -- 列出索引
\dv             -- 列出视图
\dn             -- 列出 schema
\q              -- 退出
\?              -- 帮助
\h SELECT       -- SQL 帮助

-- 执行文件
\i /path/to/file.sql

-- 输出到文件
\o output.txt
SELECT * FROM users;
\o

-- 显示执行时间
\timing on

用户管理

-- 创建用户
CREATE USER username WITH PASSWORD 'password';

-- 创建超级用户
CREATE USER admin WITH SUPERUSER PASSWORD 'password';

-- 授权
GRANT ALL PRIVILEGES ON DATABASE mydb TO username;
GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO username;
GRANT USAGE ON SCHEMA public TO username;

-- 修改密码
ALTER USER username WITH PASSWORD 'newpassword';

-- 删除用户
DROP USER username;

-- 查看用户
\du
SELECT * FROM pg_user;

数据库操作

-- 创建数据库
CREATE DATABASE mydb;
CREATE DATABASE mydb OWNER username;
CREATE DATABASE mydb ENCODING 'UTF8';

-- 删除数据库
DROP DATABASE mydb;

-- 重命名
ALTER DATABASE oldname RENAME TO newname;

-- 查看数据库
\l
SELECT datname FROM pg_database;

表操作

创建表

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(100) NOT NULL,
    password VARCHAR(255) NOT NULL,
    age INTEGER CHECK (age >= 0),
    balance DECIMAL(10, 2) DEFAULT 0.00,
    is_active BOOLEAN DEFAULT true,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 带外键
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
    amount DECIMAL(10, 2) NOT NULL,
    status VARCHAR(20) DEFAULT 'pending',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

修改表

-- 添加列
ALTER TABLE users ADD COLUMN phone VARCHAR(20);

-- 删除列
ALTER TABLE users DROP COLUMN phone;

-- 修改列类型
ALTER TABLE users ALTER COLUMN email TYPE VARCHAR(150);

-- 重命名列
ALTER TABLE users RENAME COLUMN email TO user_email;

-- 添加约束
ALTER TABLE users ADD CONSTRAINT email_unique UNIQUE (email);
ALTER TABLE users ADD CHECK (age >= 18);

-- 删除约束
ALTER TABLE users DROP CONSTRAINT email_unique;

-- 重命名表
ALTER TABLE users RENAME TO members;

-- 删除表
DROP TABLE users;
DROP TABLE IF EXISTS users CASCADE;

CRUD 操作

插入

-- 单条插入
INSERT INTO users (username, email, password)
VALUES ('john', 'john@example.com', 'hash123');

-- 多条插入
INSERT INTO users (username, email, password) VALUES
    ('alice', 'alice@example.com', 'hash1'),
    ('bob', 'bob@example.com', 'hash2');

-- 插入并返回
INSERT INTO users (username, email, password)
VALUES ('jane', 'jane@example.com', 'hash')
RETURNING id, username;

-- 冲突处理
INSERT INTO users (username, email, password)
VALUES ('john', 'john@example.com', 'hash')
ON CONFLICT (username) DO UPDATE SET email = EXCLUDED.email;

INSERT INTO users (username, email, password)
VALUES ('john', 'john@example.com', 'hash')
ON CONFLICT DO NOTHING;

查询

-- 基础查询
SELECT * FROM users;
SELECT id, username FROM users WHERE id = 1;

-- 条件查询
SELECT * FROM users WHERE age > 18 AND is_active = true;
SELECT * FROM users WHERE username LIKE 'j%';
SELECT * FROM users WHERE email ILIKE '%@gmail.com';  -- 不区分大小写
SELECT * FROM users WHERE age BETWEEN 18 AND 30;
SELECT * FROM users WHERE id IN (1, 2, 3);
SELECT * FROM users WHERE phone IS NULL;

-- 排序分页
SELECT * FROM users ORDER BY created_at DESC;
SELECT * FROM users ORDER BY age ASC NULLS LAST;
SELECT * FROM users LIMIT 10 OFFSET 20;

-- 聚合
SELECT COUNT(*) FROM users;
SELECT AVG(age), MAX(age), MIN(age) FROM users;
SELECT status, COUNT(*) FROM orders GROUP BY status;
SELECT status, COUNT(*) FROM orders GROUP BY status HAVING COUNT(*) > 10;

-- 去重
SELECT DISTINCT status FROM orders;

-- 别名
SELECT username AS name, email AS mail FROM users;

更新

-- 基础更新
UPDATE users SET email = 'new@example.com' WHERE id = 1;

-- 多字段更新
UPDATE users SET
    email = 'new@example.com',
    updated_at = CURRENT_TIMESTAMP
WHERE id = 1;

-- 更新并返回
UPDATE users SET age = age + 1 WHERE id = 1 RETURNING *;

删除

-- 删除记录
DELETE FROM users WHERE id = 1;

-- 删除并返回
DELETE FROM users WHERE id = 1 RETURNING *;

-- 清空表
TRUNCATE TABLE users;
TRUNCATE TABLE users RESTART IDENTITY CASCADE;

连接查询

-- INNER JOIN
SELECT u.username, o.amount
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

-- LEFT JOIN
SELECT u.username, o.amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

-- RIGHT JOIN
SELECT u.username, o.amount
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;

-- FULL JOIN
SELECT u.username, o.amount
FROM users u
FULL JOIN orders o ON u.id = o.user_id;

-- 多表连接
SELECT u.username, o.amount, p.name
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN products p ON o.product_id = p.id;

索引

-- 创建索引
CREATE INDEX idx_username ON users(username);
CREATE UNIQUE INDEX idx_email ON users(email);
CREATE INDEX idx_name_age ON users(username, age);

-- 部分索引
CREATE INDEX idx_active_users ON users(username) WHERE is_active = true;

-- 表达式索引
CREATE INDEX idx_lower_email ON users(LOWER(email));

-- 查看索引
\di
SELECT * FROM pg_indexes WHERE tablename = 'users';

-- 删除索引
DROP INDEX idx_username;

-- 重建索引
REINDEX INDEX idx_username;
REINDEX TABLE users;

事务

-- 开始事务
BEGIN;

-- 执行操作
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

-- 提交
COMMIT;

-- 回滚
ROLLBACK;

-- 保存点
BEGIN;
UPDATE users SET age = 30 WHERE id = 1;
SAVEPOINT sp1;
UPDATE users SET age = 40 WHERE id = 2;
ROLLBACK TO sp1;
COMMIT;

视图

-- 创建视图
CREATE VIEW active_users AS
SELECT id, username, email FROM users WHERE is_active = true;

-- 使用视图
SELECT * FROM active_users;

-- 物化视图
CREATE MATERIALIZED VIEW user_stats AS
SELECT status, COUNT(*) as count FROM orders GROUP BY status;

-- 刷新物化视图
REFRESH MATERIALIZED VIEW user_stats;

-- 删除视图
DROP VIEW active_users;

JSON 操作

-- JSON 类型
CREATE TABLE events (
    id SERIAL PRIMARY KEY,
    data JSONB
);

-- 插入 JSON
INSERT INTO events (data) VALUES ('{"name": "click", "page": "/home"}');

-- 查询 JSON
SELECT data->>'name' FROM events;
SELECT data->'page' FROM events;
SELECT * FROM events WHERE data->>'name' = 'click';
SELECT * FROM events WHERE data @> '{"name": "click"}';

-- 更新 JSON
UPDATE events SET data = data || '{"count": 1}' WHERE id = 1;
UPDATE events SET data = jsonb_set(data, '{count}', '2') WHERE id = 1;

备份恢复

# 备份数据库
pg_dump -U postgres mydb > backup.sql
pg_dump -U postgres -Fc mydb > backup.dump  # 自定义格式

# 备份所有数据库
pg_dumpall -U postgres > all_backup.sql

# 恢复
psql -U postgres mydb < backup.sql
pg_restore -U postgres -d mydb backup.dump

# 只备份结构
pg_dump -U postgres --schema-only mydb > schema.sql

# 只备份数据
pg_dump -U postgres --data-only mydb > data.sql

配置文件

主要配置文件:

  • postgresql.conf - 主配置
  • pg_hba.conf - 访问控制
# 查看配置文件位置
SHOW config_file;
SHOW hba_file;

postgresql.conf

# 监听地址
listen_addresses = '*'

# 端口
port = 5432

# 最大连接数
max_connections = 200

# 内存设置
shared_buffers = 256MB
work_mem = 4MB

# 日志
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d.log'

pg_hba.conf

# TYPE  DATABASE  USER  ADDRESS       METHOD
local   all       all                 peer
host    all       all   127.0.0.1/32  md5
host    all       all   0.0.0.0/0     md5

重载配置:

sudo systemctl reload postgresql
# 或
SELECT pg_reload_conf();

性能优化

-- 查看执行计划
EXPLAIN SELECT * FROM users WHERE username = 'john';
EXPLAIN ANALYZE SELECT * FROM users WHERE username = 'john';
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) SELECT * FROM users WHERE id = 1;

-- 查看表统计
SELECT * FROM pg_stat_user_tables WHERE relname = 'users';

-- 查看表大小
SELECT pg_size_pretty(pg_total_relation_size('users'));
SELECT pg_size_pretty(pg_database_size('mydb'));

-- 更新统计信息
ANALYZE users;
ANALYZE;  -- 分析所有表

-- 清理死元组
VACUUM users;
VACUUM FULL users;  -- 完全清理,会锁表
VACUUM ANALYZE users;  -- 清理并更新统计

-- 查看当前连接
SELECT * FROM pg_stat_activity;
SELECT pid, usename, application_name, client_addr, state, query 
FROM pg_stat_activity WHERE state = 'active';

-- 终止查询
SELECT pg_cancel_backend(pid);      -- 取消查询
SELECT pg_terminate_backend(pid);   -- 终止连接

-- 查看锁
SELECT * FROM pg_locks WHERE NOT granted;

-- 查看慢查询(需开启日志)
SELECT * FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10;

推荐配置参数

# postgresql.conf - 根据服务器配置调整

# 内存设置(假设 8GB 内存服务器)
shared_buffers = 2GB              # 总内存的 25%
effective_cache_size = 6GB        # 总内存的 75%
work_mem = 64MB                   # 排序/哈希操作内存
maintenance_work_mem = 512MB      # 维护操作内存

# 连接设置
max_connections = 200

# WAL 设置
wal_buffers = 64MB
checkpoint_completion_target = 0.9
max_wal_size = 2GB
min_wal_size = 1GB

# 查询优化
random_page_cost = 1.1            # SSD 设置为 1.1,HDD 保持 4.0
effective_io_concurrency = 200    # SSD 设置为 200

# 日志设置
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d.log'
log_statement = 'ddl'             # none, ddl, mod, all
log_min_duration_statement = 1000 # 记录超过 1 秒的查询

常用运维命令

数据库信息查询

-- 查看 PostgreSQL 版本
SELECT version();

-- 查看当前数据库
SELECT current_database();

-- 查看当前用户
SELECT current_user;

-- 查看所有配置
SHOW ALL;
SHOW shared_buffers;
SHOW max_connections;

-- 查看数据库大小
SELECT datname, pg_size_pretty(pg_database_size(datname)) 
FROM pg_database ORDER BY pg_database_size(datname) DESC;

-- 查看表大小排行
SELECT relname, pg_size_pretty(pg_total_relation_size(relid))
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 10;

-- 查看索引使用情况
SELECT indexrelname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC;

-- 查看未使用的索引
SELECT indexrelname FROM pg_stat_user_indexes WHERE idx_scan = 0;

导入导出数据

# 导出为 CSV
psql -U postgres -d mydb -c "\copy users TO 'users.csv' WITH CSV HEADER"

# 导入 CSV
psql -U postgres -d mydb -c "\copy users FROM 'users.csv' WITH CSV HEADER"

# SQL 方式导出
COPY users TO '/tmp/users.csv' WITH CSV HEADER;

# SQL 方式导入
COPY users FROM '/tmp/users.csv' WITH CSV HEADER;

定时备份脚本

Linux:

#!/bin/bash
# backup_postgres.sh

BACKUP_DIR="/var/backups/postgresql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="mydb"
DB_USER="postgres"

# 创建备份目录
mkdir -p $BACKUP_DIR

# 执行备份
pg_dump -U $DB_USER -Fc $DB_NAME > $BACKUP_DIR/${DB_NAME}_${DATE}.dump

# 删除 7 天前的备份
find $BACKUP_DIR -name "*.dump" -mtime +7 -delete

echo "Backup completed: ${DB_NAME}_${DATE}.dump"

Windows(PowerShell):

# backup_postgres.ps1

$BackupDir = "C:\Backups\PostgreSQL"
$Date = Get-Date -Format "yyyyMMdd_HHmmss"
$DbName = "mydb"
$PgDump = "C:\Program Files\PostgreSQL\16\bin\pg_dump.exe"

# 创建备份目录
New-Item -ItemType Directory -Force -Path $BackupDir

# 设置密码环境变量
$env:PGPASSWORD = "your_password"

# 执行备份
& $PgDump -U postgres -Fc $DbName -f "$BackupDir\${DbName}_${Date}.dump"

# 删除 7 天前的备份
Get-ChildItem $BackupDir -Filter "*.dump" | Where-Object {
    $_.LastWriteTime -lt (Get-Date).AddDays(-7)
} | Remove-Item

Write-Host "Backup completed: ${DbName}_${Date}.dump"

总结

PostgreSQL 特点:

  • 完整的 SQL 标准支持
  • 强大的 JSON 支持
  • 丰富的数据类型
  • 可靠的事务处理
  • 优秀的扩展性

常用端口:5432

配置文件位置:

  • Linux: /etc/postgresql/版本/main//var/lib/pgsql/版本/data/
  • Windows: C:\Program Files\PostgreSQL\版本\data\

数据目录:

  • Linux: /var/lib/postgresql/版本/main/
  • Windows: C:\Program Files\PostgreSQL\版本\data\

适合需要复杂查询和数据完整性的应用场景。

评论

加载评论中...