主键定义索引与CREATE INDEX子句的差异及5亿条记录大表查询咨询
嘿,咱们把问题拆成两部分来聊,先搞清楚主键索引和CREATE INDEX创建的普通索引的核心区别,再针对你那5亿条记录的表的情况给点实际建议~
主键索引 vs 普通CREATE INDEX的关键区别
虽然两者都是索引,但本质上是为不同目的设计的,核心差异主要有这几点:
- 唯一性&非空强制:主键索引自带唯一非空约束——数据库会严格检查主键列(或组合列)的值,不允许重复,也不能为NULL。而普通索引(除非你显式加
UNIQUE关键字)默认允许重复值,也不限制非空。简单说,主键是用来唯一标识行的,普通索引只是用来加速查询的。 - 创建与绑定关系:主键通常是在建表时通过
PRIMARY KEY约束声明的(就像你示例里的CONSTRAINT "PK_CSC_CUSTOMER_PREPAID_BAL" PRIMARY KEY ("ID_COMPANY", "SEQUENTIAL_MOV")),数据库会自动为这个约束生成对应的唯一索引。而普通索引是通过单独的CREATE INDEX idx_name ON table(col)语句创建的,属于独立的数据库对象。另外,如果你删除主键约束,对应的主键索引也会被一起删掉;但普通索引和约束(如果有的话)是分离的,删除约束不影响索引。 - 索引类型(以Oracle为例):你的建表语句用的是Oracle,这里主键默认会生成唯一B树索引;普通索引如果没加
UNIQUE,就是非唯一B树索引。 - 用途优先级:主键索引是表的核心定位键,数据库在做JOIN、主键精确查找时会优先选用它;普通索引则是为了优化特定查询的过滤、排序场景,比如你经常按某个非主键列查询,就建普通索引来加速。
针对你5亿条记录表的查询优化建议
从你的描述看,这张表的ID_COMPANY全是1,主键是组合键(ID_COMPANY, SEQUENTIAL_MOV),这种情况会带来一些性能问题,给你几个方向参考:
- 主键索引的实际效率:组合索引的前缀列(
ID_COMPANY)重复率100%,相当于这个组合索引几乎等价于单独给SEQUENTIAL_MOV建的索引,但因为前缀的存在,索引的区分度极低。如果你的查询是WHERE ID_COMPANY=1 AND SEQUENTIAL_MOV=?这种精确匹配,主键索引还能快速定位;但如果是范围查询(比如SEQUENTIAL_MOV BETWEEN ? AND ?),索引扫描的范围会覆盖几乎所有数据,和全表扫描差别不大。 - 分区表优化(强烈推荐):5亿条数据单表太大,建议把表按
SEQUENTIAL_MOV做范围分区(比如按数值区间分成几十个分区)。这样查询时只需要扫描目标分区,不用遍历整个大表,性能会有质的提升。 - 统计信息维护:Oracle的优化器依赖准确的统计信息,5亿条数据的表一定要确保统计信息是最新的——可以定期执行
DBMS_STATS.GATHER_TABLE_STATS('BIDATA', 'CSC_CUSTOMER_PREPAID_BALANCE')来更新,避免优化器选错执行计划。 - 额外索引的权衡:如果有其他查询维度(比如按
ID_PAYMENT查询),可以考虑建普通索引,但要注意:5亿条数据的索引创建和维护成本极高(插入、更新时要同步更新索引),所以只给查询频率极高的列建索引,别乱建。
内容的提问来源于stack exchange,提问作者Jav
相关产品推荐
相关产品推荐

