MySQL 時(shí)間類(lèi)型 datetime、bigint、timestamp,選哪個(gè)?

源 / 文/
數(shù)據(jù)庫(kù)中可以用datetime、bigint、timestamp來(lái)表示時(shí)間,那么選擇什么類(lèi)型來(lái)存儲(chǔ)時(shí)間比較合適呢?
前期數(shù)據(jù)準(zhǔn)備
通過(guò)程序往數(shù)據(jù)庫(kù)插入50w數(shù)據(jù)
數(shù)據(jù)表:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`time_date` datetime NOT NULL,
`time_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`time_long` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `time_long` (`time_long`),
KEY `time_timestamp` (`time_timestamp`),
KEY `time_date` (`time_date`)
) ENGINE=InnoDB AUTO_INCREMENT=500003 DEFAULT CHARSET=latin1
其中time_long、time_timestamp、time_date為同一時(shí)間的不同存儲(chǔ)格式
實(shí)體類(lèi)users
/**
* @author hetiantian
* @date 2018/10/21
* */
@Builder
@Data
public class Users {
/**
* 自增唯一id
* */
private Long id;
/**
* date類(lèi)型的時(shí)間
* */
private Date timeDate;
/**
* timestamp類(lèi)型的時(shí)間
* */
private Timestamp timeTimestamp;
/**
* long類(lèi)型的時(shí)間
* */
private long timeLong;
}
dao層接口
/**
* @author hetiantian
* @date 2018/10/21
* */
@Mapper
public interface UsersMapper {
@Insert("insert into users(time_date, time_timestamp, time_long) value(#{timeDate}, #{timeTimestamp}, #{timeLong})")
@Options(useGeneratedKeys = true,keyProperty = "id",keyColumn = "id")
int saveUsers(Users users);
}
測(cè)試類(lèi)往數(shù)據(jù)庫(kù)插入數(shù)據(jù)
public class UsersMapperTest extends BaseTest {
@Resource
private UsersMapper usersMapper;
@Test
public void test() {
for (int i = 0; i < 500000; i++) {
long time = System.currentTimeMillis();
usersMapper.saveUsers(Users.builder().timeDate(new Date(time)).timeLong(time).timeTimestamp(new Timestamp(time)).build());
}
}
}
sql查詢速率測(cè)試
通過(guò)datetime類(lèi)型查詢:
select count(*) from users where time_date >="2018-10-21 23:32:44" and time_date <="2018-10-21 23:41:22"
耗時(shí):0.171
通過(guò)timestamp類(lèi)型查詢
select count(*) from users where time_timestamp >= "2018-10-21 23:32:44" and time_timestamp <="2018-10-21 23:41:22"
耗時(shí):0.351
通過(guò)bigint類(lèi)型查詢
select count(*) from users where time_long >=1540135964091 and time_long <=1540136482372
耗時(shí):0.130s
結(jié)論 在InnoDB存儲(chǔ)引擎下,通過(guò)時(shí)間范圍查找,性能bigint > datetime > timestamp
sql分組速率測(cè)試
使用bigint 進(jìn)行分組會(huì)每條數(shù)據(jù)進(jìn)行一個(gè)分組,如果將bigint做一個(gè)轉(zhuǎn)化在去分組就沒(méi)有比較的意義了,轉(zhuǎn)化也是需要時(shí)間的
通過(guò)datetime類(lèi)型分組:
select time_date, count(*) from users group by time_date
耗時(shí):0.176s
通過(guò)timestamp類(lèi)型分組:
select time_timestamp, count(*) from users group by time_timestamp
耗時(shí):0.173s
結(jié)論 在InnoDB存儲(chǔ)引擎下,通過(guò)時(shí)間分組,性能timestamp > datetime,但是相差不大
sql排序速率測(cè)試
通過(guò)datetime類(lèi)型排序:
select * from users order by time_date
耗時(shí):1.038s
通過(guò)timestamp類(lèi)型排序
select * from users order by time_timestamp
耗時(shí):0.933s
通過(guò)bigint類(lèi)型排序
select * from users order by time_long
耗時(shí):0.775s
結(jié)論 在InnoDB存儲(chǔ)引擎下,通過(guò)時(shí)間排序,性能bigint > timestamp > datetime
小結(jié)
如果需要對(duì)時(shí)間字段進(jìn)行操作(如通過(guò)時(shí)間范圍查找或者排序等),推薦使用bigint,如果時(shí)間字段不需要進(jìn)行任何操作,推薦使用timestamp,使用4個(gè)字節(jié)保存比較節(jié)省空間,但是只能記錄到2038年記錄的時(shí)間有限。

推薦閱讀


某程序員披露華為外包員工現(xiàn)狀:工作氛圍好,沒(méi)有歧視,但轉(zhuǎn)正后也不算正式員工?

字節(jié)跳動(dòng)小組長(zhǎng)無(wú)意中得知整個(gè)部門(mén)的薪資!自己只有28K!手下人卻拿35K!怎么辦?

太尷尬!百度某程序員向領(lǐng)導(dǎo)請(qǐng)假去面試,卻在面試一樓大廳和領(lǐng)導(dǎo)相遇,網(wǎng)友:緣分啊!回去一起對(duì)對(duì)面試題!
END


頂級(jí)程序員:topcoding
做最好的程序員社區(qū):Java后端開(kāi)發(fā)、Python、大數(shù)據(jù)、AI
一鍵三連「分享」、「點(diǎn)贊」和「在看」
