数据库表设计需平衡一致性、查询效率与维护成本,以3NF为基座,在查多写少、稳定不变、逻辑简单的场景下局部反范式化,并重视索引、分区、UTC时间等物理设计与演进意识。
数据库表结构设计不是单纯追求理论完美,而是平衡一致性、查询效率和维护成本。范式化能减少冗余、保障数据完整性,反范式化则常用于提升读性能——关键不在“该不该范式”,而在“在什么场景下做何种取舍”。
实际建表中,真正需要严格遵守的是1NF(字段原子性)、2NF(消除非主属性对部分主键的依赖)和3NF(消除传递依赖)。BCNF和更高范式多见于理论或特殊强一致性系统,业务系统中过度追求反而增加JOIN复杂度。
user_tags(user_id, tag_name)。(order_id, product_id)作主键,但product_name只依赖product_id,就存在部分依赖;应将产品信息抽离至products表,明细表仅保留product_id外键。city_name和province_name,而城市归属省份是确定关系,province_name实际依赖city_name而非user_id;应建立cities和provinces字典表,用户表只存city_id。反范式不是随意加字段,而是针对高频、低更新、强聚合需求的场景,用可控冗余换性能。前提是明确冗余字段的更新机制,避免数据不一致。
sales_count字段,每次下单后通过事务内UPDATE+1更新;比实时COUNT(*)快得多,且更新路径唯一、不易出错。user_nickname和product_title,前提是这些字段极少修改(昵称改名频率低、商品标题基本不变),且业务允许几秒
级延迟(可通过MQ异步刷新)。成熟系统往往以3NF为底座,在少数关键路径上局部反范式。设计时建议按“查多写少、稳定不变、逻辑简单”三原则筛选反范式点。
再好的逻辑设计,若缺少索引、分区或字符集支持,也会失效。同时,表结构不是上线即定稿——应预留扩展性,比如用jsonb(PostgreSQL)或JSON(MySQL 5.7+)存储非结构化、低查询频率的扩展属性,比不停加字段更可持续。
created_at、updated_at,必要时加deleted_at支持软删除。