这是我参与「第五届青训营 」伴学笔记创作活动的第 13 天
前言
大家好呀,这是我参加青训营伴学笔记创作活动的第 13 天,如存在问题,烦请各位斧正!
其中有一些关键图片超过了最大字符限制,不能上传了,我都使用特殊标记给它标记出来了,如有需要,请联系我。
入门使用
概述
1)ORM:Object Relational Mapping(对象关系映射):
即在golang中,自定义的一个结构体对应着一张表,结构体的实例则对应着表中的一条记录。
2)安装:
go get github.com/jinzhu/gorm
声明模型
采用约定优于配置原则:
1)模型名和表名的映射规则:首字母变小写、尾部加复数,多个值会变为下划线连接:
(1)举例:
User => users UserInfo => user_infos(2)
db.SingularTable(true)让grom转义struct名字的时候不用加上s2)数据模型:
type User struct {
Id int
Name string
Age int
}
3)嵌套:也可以抽取出公共元素放到Model,然后让User有Model属性,就相当于有了公共元素作为属性。
4)结构体字段名和列名的对应规则
CreatedTime --> create_time可以通过gorm标签指定列名,
AnimalId int64 gorm:"column:beast_id"
连接数据库
// 用户名:密码@tcp(ip:port)/数据库?charset=utf8mb4&parseTime=True&loc=Local
dsn := "root:a1134443466@tcp(127.0.0.1:3306)/property?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn),
&gorm.Config{})
if err != nil {
panic(err)
}
1)注意:parseTime是查询结果是否自动解析为时间。+loc是MySQL的时区设置
2)可以通过传入参数实现缓存预编译语句来提高效率:&gorm.Config{
PrepareStmt: true }
定义模型进阶
在默认表名上加其他规则
1)在默认表名前加sys_前缀
gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string {
return "sys_" + defaultTableName;
}
2)自定义表名:
func (模型) TableName() string{
return "新的表名"
}
gorm.Model
1)基本模型定义gorm.Model,包括字段ID,CreatedAt,UpdatedAt,DeletedAt
type Model struct {
ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt DeletedAt `gorm:"index"`
}
只需要在自己的模型中指定gorm.Model匿名字段,即可使用上面的四个字段
type User struct {
gorm.Model
Name string
}
结构体标签gorm的使用
type User struct {
Name string `gorm:"<-:create"` // 允许读和创建
Name string `gorm:"<-:update"` // 允许读和更新
Name string `gorm:"<-"` // 允许读和写(创建和更新)
Name string `gorm:"<-:false"` // 允许读,禁止写
Name string `gorm:"->"` // 只读(除非有自定义配置,否则禁止写)
Name string `gorm:"->;<-:create"` // 允许读和写
Name string `gorm:"->:false;<-:create"` // 仅创建(禁止从 db 读)
Name string `gorm:"-"`
// 读写操作均会忽略该字段
}
创建/更新时间追踪(纳秒、毫秒、秒、Time)
1)GORM 约定使用 CreatedAt、UpdatedAt 追踪创建/更新时间。如果您定义了这种字段,GORM 在创建、更新时会自动填充 当前时间。
2)要使用不同名称的字段,您可以配置 autoCreateTim、autoUpdateTim 标签
如果您想要保存 UNIX(毫/纳)秒时间戳,而不是 time,您只需简单地将 time.Time 修改为 int 即可:
type User struct {
CreatedAt time.Time // 在创建时,如果该字段值为零值,则使用当前时间填充
UpdatedAt int // 在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充
Updated int64 `gorm:"autoUpdateTime:nano"` // 使用时间戳填纳秒数充更新时间
Updated int64 `gorm:"autoUpdateTime:milli"` // 使用时间戳毫秒数填充更新时间
Created int64 `gorm:"autoCreateTime"` // 使用时间戳秒数填充创建时间
}
字段标签
声明 model 时,tag 是可选的,GORM 支持以下 tag: tag 名大小写不敏感:
多个属性值之间用分号分隔(英文的;):gorm:"size:64;not null"
标签名 说明
column:指定db列名列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都攴持bool、int、uint、float, string、time、 bytes并且可以和其他标签一起使用,例如: not null、size,autoincrement.像 varbinary(8)这样指定数据库数据类型也是支持的。
在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如: MEDIUMINT UNSIGNED not NULLAUTO INSTREMENT
size:指定列大小,例如:size:256primarykey指定列为主键指定列为唯default指定列的默认值precision指定列的精度scale指定列大指定列为 NOT NULLautoincrement指定列为自动增长embedded嵌套字段
embedded Prefix嵌入字段的列名前缀时追踪当前时nt字段,它会追踪时间戳秒数nano/ mill来追踪纳auto
create time亳秒时间戳,例如: autocreate Time:nano创建更新时追踪当前时间,对于int字段,它会追踪时间戳秒数,您可以使用nano/m来追auto
update Time踪纳秒、亳秒时间戳,例如: autoupdate Time:mindex根据参数创建索引,多个字段使用相同的名称则创建复合索引,查看索引获取详
uniqueindexndex相同建的是唯一索chec创建检查约束,例如 check:age>13,查看约束获取详设置字段写入的权限,<-: create只仓date只更新、< false无写入权限、<创建和更新权限字段读的权限,->fase无读权限忽略该字段,-无读写权
order by优化
1、MySQL的排序,有两种方式:
1)Using filesort : 通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sortbuffer中完成排序操作,
所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。
2)Using index : 通过有序索引顺序扫描直接返回有序数据,这种情况即为 using index,不需要额外排序,操作效率高。
3)对于以上的两种排序方式,Using index的性能高,而Using filesort的性能低,我们在优化排序操作时,尽量要优化为 Using index。
4)使用explain可以查看执行计划中的Extra字段是上述两者中的哪一种。
2、优化
1)假如要根据字段进行降序排序,但是此时Extra中出现了 Backward index scan,这个代表反向扫描索引,因为在MySQL中我们创建的索引,
默认索引的叶子节点是从小到大排序的,而此时我们查询排序时,是从大到小,所以,在扫描时,就是反向扫描,就会出现 Backward index scan。
在MySQL8版本中,支持降序索引,我们也可以创建降序索引。
2)创建索引时,如果未指定顺序,默认都是按照升序排序的,而查询时,一个升序,一个降序,此时 就会出现Using filesort。
创建联合索引时,可以让两个字段有不同的升降序:create index idx_user_age_phone_ad on tb_user(age asc ,phone desc);
3)其他优化原则:
(1)根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。
(2)尽量使用覆盖索引。
(3)如果不可避免的出现filesort,大数据量排序时,可以适当增大排序缓冲区大小sort_buffer_size(默认256k)。