bad case:在activity_spring_red_packet_sync表的设计过程中,将id,user_id,date三列作为了一个复合主键。
上述情况有哪些不妥的地方?
一、sql语句
CREATE TABLE `activity_spring_red_packet_sync` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`phone` char(15) NOT NULL COMMENT '用户手机号',
`date` date NOT NULL COMMENT '发送日期',
`remain_send_times` int(11) NOT NULL COMMENT '剩余可发红包次数',
`remain_get_times` int(11) NOT NULL COMMENT '剩余领取红包次数',
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`,`user_id`,`date`),
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=latin1 COMMENT='春节活动收发红包次数';
二、问题分析
- 什么是联合索引,和复合索引有什么区别?
- 当两个数据表形成的是多对多的关系,那么需要通过两个数据表的主键来组成联合主键,就可以确定每个数据表的其中一条记录了
- 在一个数据表中通过多个字段作为主键来确定一条记录,那么,多个字段组成的就是复合主键
- 复合主键的弊端?
- 如果有频繁的业务修改,会导致非聚集索引中的主键信息相应修改,而且容易造成表中记录的物理移动。
- 生成有业务含义的字段需要按照一定的规则生成,不可避免使用varchar等字符串类型,影响插入和查询效率。
- 业务规则发生变化,造成的影响容易扩大。
三、解决问题
- 需要的是将用户和日期作为一个唯一标识;
- 利用索引 UNIQUE KEY
PRIMARY KEY (`id`),
UNIQUE KEY `SPRING_RED_PACKET_USER_DATE_IDEX` (`date`,`phone`) USING BTREE