mysql point

使用枚举(ENUM)代替字符串

枚举列可以把一些不重复的字符串存储成一个预定义的集合。MySQL 在存储枚举时非常紧凑,会根据列表值的数量压缩到一个或者两个字节中。MySQL 在内部会将每个值在列表中的位置保存为整数,并且在表的.frm文件中保存 “数字-字符串” 映射关系的 “查找表”。

代码 3. 测试枚举的存储值

DROPTABLEIFEXISTSenum_test;CREATETABLEenum_test (e ENUM ('fish', 'apple', 'dog'));INSERTINTOenum_test (e)VALUES('fish'), ('dog'), ('apple');(1)SELECTe + 0FROMenum_test;SELECTeFROMenum_testORDERBYe;(2)SELECTeFROMenum_testORDERBYfield(e, 'apple', 'dog', 'fish');(3)

1三行数据实际存储为整数,而不是字符串。

2测试排序性

3根据定义的字符串排序

如果使用数字作为ENUM枚举常量,很容易导致混乱。尽量避免这么做。

DATETIME

保存大范围的值,从 1001 年到 9999 年,精度为秒。把日期和时间封装到格式为 YYYYMMDDHHMMSS 的整数中,与时区无关。使用 8 个字节的存储空间。

TIMESTAMP

保存从 1970 年 1 月 1 日午夜以来的秒数,和 UNIX 时间戳相同。TIMESTAMP只使用 4 个字节的存储空间,范围是从 1970 年到 2038 年。

TIMESTAMP显示的值也依赖于时区。MySQL 服务器、操作系统以及客户端连接都有时区设置。因此,存储值为 0 的TIMESTAMP在美国东部时区显示为 “1969-12-31 19:00:00”,与格林尼治时间差5个小时。

如果在多个时区存储或访问数据,TIMESTAMP和DATETIME的行为将会很不一样。前者提供的值与时区有关,后者则保留文本表示的日期和时间。

默认情况下,如果插入时没有指定第一个TIMESTAMP列的值,MySQL 则设置这个列的值为当前时间。

TIMESTAMP列默认为NOT NULL。

通常应该尽量使用TIMESTAMP,因为它比DATETIME空间效率更高。

可以使用BIGINT类型存储微秒级别的时间戳,或者使用DOUBLE存储秒之后的小数部分。

计数器表

可以利用CurrentHashMap分段锁的思想,将对同一个计算器的修改,打散到多个变量上,然后在求和。

DROPTABLEIFEXISTShit_counter;CREATETABLEhit_counter (

slot TINYINT UNSIGNEDNOTNULLPRIMARYKEY,

cnt  INT UNSIGNEDNOTNULL

)ENGINE= InnoDB;UPDATEhit_counterSETcnt = cnt + 1WHEREslot = RAND() * 100;SELECTSUM(cnt)FROMhit_counter;

一个常见需要时每个一段时间开始一个新的计算器(例如,每天一个)。

DROPTABLEIFEXISTSdaily_hit_counter;CREATETABLEdaily_hit_counter (

day  DATENOTNULL,

slot TINYINT UNSIGNEDNOTNULL,

cnt  INT UNSIGNEDNOTNULL,PRIMARYKEY(day, slot)

)ENGINE= InnoDB;-- 插入数据INSERTINTOdaily_hit_counter (day, slot, cnt)VALUES(current_date, rand() * 100, 1)ONDUPLICATEKEYUPDATEcnt = cnt + 1;-- 定期执行:合并所有结果到 0 号槽,并且删除所有其他的槽:UPDATEdaily_hit_counterAScINNERJOIN(SELECTday,

sum(cnt)AScnt,

min(slot)ASmslotFROMdaily_hit_counterGROUPBYday

)ASxUSING(day)SETc.cnt =if(c.slot = x.mslot, x.cnt, 0),

c.slot  =if(c.slot = x.mslot, 0, c.slot);DELETEFROMdaily_hit_counterWHEREslot <> 0ANDcnt = 0;

统计同一列的不同值的数量,以减少查询的语句量。可以这样:

DROPTABLEIFEXISTSitems;CREATETABLEitems (

id    INTEGERAUTO_INCREMENTPRIMARYKEY,

color VARCHAR(50)

);SELECTSUM(IF(color = 'blue', 1, 0))ASblue,

SUM(IF(color = 'red', 1, 0))ASredFROMitems;SELECTCOUNT(color = 'blue'ORNULL)ASblue,

COUNT(color = 'red'ORNULL)ASredFROMitems;

你可能感兴趣的:(mysql point)