SQL 架构复杂度的控制策略

表设计应拒绝大宽表,按业务变更频率拆分;外键需显式声明但避免跨服务强依赖;枚举字段须建独立表并加CHECK约束;视图仅用于简单过滤,复杂聚合用物化视图;索引须匹配真实查询模式,复合索引顺序关键;迁移脚本必须可重入且带验证。

sql 架构复杂度的控制策略

表设计阶段就要拒绝“大宽表”

宽表在初期看似省事,但很快会成为查询性能、权限管理、变更风险的源头。字段超过 30 列的表,大概率存在职责混杂——比如把用户基本信息、订单统计、风控标签全塞进 users 表里。

  • 拆分依据不是“能不能 JOIN”,而是“业务变更频率是否一致”:用户资料每月改一次,而登录日志每秒写入,必须分离到 usersuser_login_events
  • 外键约束宁可显式声明,也不要靠应用层“保证一致性”;但也要避免跨微服务强外键,此时用逻辑关联 + 定期校验更实际
  • 枚举类字段(如 status)别用字符串硬编码,建独立 status_types 表并加 CHECK 约束,否则后续改名或扩值域时全库 UPDATE 风险极高

视图和物化视图的使用边界

视图不是银弹。普通 VIEW 只是保存 SQL 文本,嵌套三层后,SELECT * 可能触发全表扫描+重复计算,而你根本没意识到。

  • 简单查询封装(如过滤掉已删除记录)用 VIEW 没问题:CREATE VIEW active_orders AS SELECT * FROM orders WHERE deleted_at IS NULL
  • 涉及多表聚合、窗口函数、或高频访问的报表逻辑,优先考虑物化视图(PostgreSQL 9.3+ 的 MATERIALIZED VIEW,或 MySQL 用定时任务+汇总表)
  • 物化视图更新策略必须明确:是 REFRESH CONCURRENTLY(PG),还是容忍几分钟延迟?千万别在事务里调 REFRESH MATERIALIZED VIEW,它会锁整个视图

索引不是越多越好,而是要匹配查询模式

加索引前先看慢查询日志里真实出现的 WHEREJOINORDER BY 组合,而不是凭感觉给所有 idcreated_at 加索引。

NetShop网店系统

NetShop网店系统

NetShop软件特点介绍: 1、使用ASP.Net(c#)2.0、多层结构开发 2、前台设计不采用任何.NET内置控件读取数据,完全标签化模板处理,加快读取速度3、安全的数据添加删除读取操作,利用存储过程模式彻底防制SQL注入式攻击4、前台架构DIV+CSS兼容IE6,IE7,FF等,有利于搜索引挚收录5、后台内置强大的功能,整合多家网店系统的功能,加以优化。6、支持三种类型的数据库:Acces

下载

  • 复合索引顺序至关重要:WHERE a = ? AND b > ? ORDER BY c 最佳索引是 (a, b, c),反过来就失效
  • LIKE '%abc' 无法走 B-tree 索引,这类搜索要么用全文索引(tsvector),要么前置生成反向字符串索引
  • 删除长期未被 pg_stat_all_indexes.idx_scan 记录使用的索引,它们只拖慢写入、增大备份体积

迁移脚本必须可重入且带验证

ALTER TABLE ADD COLUMN 看似安全,但如果脚本重复执行,可能报错“column already exists”,导致自动化发布中断。

  • 所有 DDL 脚本开头加判断:DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = 'orders'::regclass AND attname = 'paid_at') THEN ALTER TABLE orders ADD COLUMN paid_at TIMESTAMPTZ; END IF; END $$;
  • 变更后立刻跟验证语句,比如加了非空约束,就跑 SELECT COUNT(*) FROM orders WHERE new_column IS NULL,不为 0 就中止后续步骤
  • 生产环境禁止直接 DROP COLUMN,先设为 NULL、删默认值、应用层停写、确认无读取后再真正删除

复杂度控制真正的难点不在技术选型,而在团队对“什么算合理拆分”的共识。一个字段该不该进这张表,往往卡在产品、后端、DBA 对同一业务术语的理解偏差上。这时候,比 SQL 更重要的是那张贴在白板上的实体关系草图,以及每次评审时敢问一句:“这个字段下次改的时候,会影响多少个服务?”

https://www.php.cn/faq/2022972.html

发表回复

Your email address will not be published. Required fields are marked *