概览MySQL篇一:索引

极客时间《MySQL实战45讲》笔记 索引是什么,为何存在,以什么样的结构组织或存储索引? 简单来说,索引是一个目录,用来对数据进行快速的查找。就像一本厚厚的字典,想要查询某个字或者词语,我们固然可以一页页翻阅整本词典,但更好的方式是通过拼音索引或者笔画索引到这条记录。 索引可以有效减小查询的资源消耗,但索引不是毫无代价的,大量的创建索引会造成存储空间的损耗,我们要根据业务需求,有目的的创建对业务有帮助的索引。 在MySQL的InnoDB引擎中,索引是以B+树的形式存在的。B+树的节点存储在物理页上。 根据叶子节点的内容,索引类型分为主键索引和非主键索引。 主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index)。 非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。 为什么更推荐使用自增主键? 自增主键是指自增列上定义的主键,在建表语句中一般是这么定义的: NOT NULL PRIMARY KEY AUTO_INCREMENT。 B+树天然就是有序的,当我们想在上图中插入一个ID=400的记录,那么可能需要进行页分裂操作,这就需要挪动后面的数据。但如果想插入一个ID=700的值,只需要在最后附加一条记录就可以,不需要对前面的值就行操作。 自增主键的插入数据模式,正符合了我们前面提到的递增插入的场景。每次插入一条新记录,都是追加操作,都不涉及到挪动其他记录,也不会触发叶子节点的分裂。 除了性能外,页分裂操作还影响数据页的利用率。原本放在一个页的数据,现在分到两个页中,整体空间利用率降低大约 50%。 使用索引查询的过程是怎么样的,什么叫回表、覆盖索引? 对于如下表: mysql> create table T ( ID int primary key, k int NOT NULL DEFAULT 0, s varchar(16) NOT NULL DEFAULT '', index k(k)) engine=InnoDB; insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg'); 当执行select * from T where k between 3 and 5时,过程如下: 在 k 索引树上找到 k=3 的记录,取得 ID = 300; 再到 ID 索引树查到 ID=300 对应的 R3; 在 k 索引树取下一个值 k=5,取得 ID=500; 再回到 ID 索引树查到 ID=500 对应的 R4; 在 k 索引树取下一个值 k=6,不满足条件,循环结束。 可以看到,MySQL先在k索引树上查找满足条件的记录,拿到主键,然后再到主键索引树上去取整条记录。这个用主键去主键索引上取数据的操作就叫做回表。...

March 22, 2022 · 1 min · 李昌

切片append规则

大约2021年8月份,go社区对切片容量增长的方式进行了一次调整。具体讨论可见:https://groups.google.com/g/golang-nuts/c/UaVlMQ8Nz3o 1. 之前的增长规则 先看源码 runtime/slice.go func growslice(et *_type, old slice, cap int) slice { // 省略部分条件检查 // ... newcap := old.cap doublecap := newcap + newcap if cap > doublecap { newcap = cap } else { if old.cap < 1024 { newcap = doublecap } else { // Check 0 < newcap to detect overflow // and prevent an infinite loop. for 0 < newcap && newcap < cap { newcap += newcap / 4 } // Set newcap to the requested cap when // the newcap calculation overflowed....

March 19, 2022 · 2 min · 李昌

理解反射之:一个reflect.Type可以做什么

反射是一个接口,其定义如下: type Type interface { // 返回具体类型在内存分配时的字节分配方式 Align() int // 返回具体类型在结构体中作为一个字段是内存对齐方式 FieldAlign() int // 返回具体类型的第x个方法 Method(int) Method // 根据函数名返回具体类型的方法 MethodByName(string) (Method, bool) // 返回类型的方法个数 NumMethod() int // 返回类型的名字 Name() string // 返回类型的包名 PkgPath() string // 返回类型所占内存字节大小 Size() uintptr // 返回类型的简单描述,如:main.User String() string // 返回这个类型的Kind Kind() Kind // 检查类型是否实现了某个接口 //stringer := reflect.TypeOf((*fmt.Stringer)(nil)).Elem() //fmt.Println(reflect.ValueOf(u).Type().Implements(stringer)) Implements(u Type) bool // 检查类型是否可以被赋值给某个类型 AssignableTo(u Type) bool // 检查类型是否可以转换到类型u ConvertibleTo(u Type) bool // 检查类型是否可比较 Comparable() bool // 返回Int, Uint, Float, or Complex kinds....

March 15, 2022 · 1 min · 李昌

for...range要点

range循环时,使用的是被迭代的元素的副本 type T struct { n int } func main() { ts := [2]T{} for i, t := range ts { switch i { case 0: t.n = 3 // 被访问的是ts的副本 ts[1].n = 9 case 1: fmt.Print(t.n, " ") } } fmt.Print(ts) } 输出:0 {{0} {9}} range 循环语句使用的临时变量 func main() { h := make([]*int, 3) u := []int{1, 2, 3} for i, v := range u { h[i] = &v } for i := range h { fmt....

March 12, 2022 · 1 min · 李昌

标准库之unsafe

1. Go中对指针的限制 Go 的指针不能进行数学运算。 不同类型的指针不能相互转换。 不同类型的指针不能使用 == 或 != 比较。只有在两个指针类型相同或者可以相互转换的情况下,才可以对两者进行比较。另外,指针可以通过 == 和 != 直接和 nil 作比较。 不同类型的指针变量不能相互赋值。 使用unsafe包,可以一定程度上打破这些限制,那么为什么要打破这些限制。请看下文。 2. unsafe.Pointer unsafe.Pointer的定义 type ArbitraryType int type Pointer *ArbitraryType unsafe 包提供了 2 点重要的能力: 任何类型的指针和 unsafe.Pointer 可以相互转换。 uintptr 类型和 unsafe.Pointer 可以相互转换。 pointer 不能直接进行数学运算,但可以把它转换成 uintptr,对 uintptr 类型进行数学运算,再转换成 pointer 类型。利用这两个对象的相互转换,就可以打破上述4个限制。 // uintptr 是一个整数类型,它足够大,可以存储 type uintptr uintptr 还有一点要注意的是,uintptr 并没有指针的语义,意思就是 uintptr 所指向的对象会被 gc 无情地回收.而 unsafe.Pointer 有指针语义,可以保护它所指向的对象在“有用”的时候不会被垃圾回收。 3. 利用unsafe获取slice和map的长度 slice和map的长度都存储在其内部变量中,因此我们先来看这两个结构体定义: // runtime/slice.go type slice struct { array unsafe....

March 4, 2022 · 2 min · 李昌

静态代码检查: golangci-lint

1. 简介 golangci-lint 是对golang进行静态代码检查的工具。其具有以下特性: 速度非常快:golangci-lint 是基于 gometalinter 开发的,但是平均速度要比 gometalinter 快 5 倍。golangci-lint 速度快的原因有三个:可以并行检查代码;可以复用 go build 缓存;会缓存分析结果。 可配置:支持 YAML 格式的配置文件,让检查更灵活,更可控。 IDE 集成:可以集成进多个主流的 IDE,例如 VS Code、GNU Emacs、Sublime Text、Goland 等。 linter 聚合器:1.41.1 版本的 golangci-lint 集成了 76 个 linter,不需要再单独安装这 76 个 linter。并且 golangci-lint 还支持自定义 linter。 最小的误报数:golangci-lint 调整了所集成 linter 的默认设置,大幅度减少了误报。 良好的输出:输出的结果带有颜色、代码行号和 linter 标识,易于查看和定位。 2. 安装 # 安装 go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.41.1 # 检查是否安装成功 golangci-lint version # 输出 golangci-lint 版本号,说明安装成功 golangci-lint has version v1.44.0 built from (unknown, mod sum: "h1:YJPouGNQEdK+x2KsCpWMIBy0q6MSuxHjkWMxJMNj/DU=") on (unknown) 3....

February 9, 2022 · 2 min · 李昌

channel的行为

1. nil channel 接收 接收goroutine阻塞 发送 发送个goroutine阻塞 2. 向无缓冲channel发送消息 接受队列有goroutine 接收端将收到消息 接收队列无goroutine 发送goroutine将阻塞 已有发送goroutine阻塞 发送goroutine将阻塞 3. 从无缓冲channel接收消息 无发送goroutine 接收端阻塞 有发送goroutine 收到消息 4. 向有缓冲channel发送消息 队列未满 正常发送 队列已满 发送端阻塞 5. 从有缓冲channel接收消息 队列中有消息 正常接收 队列中无消息 接收端阻塞 6. 对close channel的操作 向closed channel发送 panic...

January 2, 2022 · 1 min · 李昌

vim配置

1. 安装插件系统 使用的是vim-plug curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim 2. 安装插件 打开~/.vimrc, 在其中写入: " Specify a directory for plugins " - For Neovim: stdpath('data') . '/plugged' " - Avoid using standard Vim directory names like 'plugin' call plug#begin('~/.vim/plugged') " Make sure you use single quotes " Shorthand notation; fetches https://github.com/junegunn/vim-easy-align Plug 'junegunn/vim-easy-align' " Any valid git URL is allowed Plug 'junegunn/vim-github-dashboard' " On-demand loading Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' } Plug 'tpope/vim-fireplace', { 'for': 'clojure' } " Using a non-default branch Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' } " Using a tagged release; wildcard allowed (requires git 1....

December 29, 2021 · 2 min · 李昌

面向对象UML图

1. 用例图 用例图主要用于定义系统的功能需求,它描述了系统的参与者与系统提供的用例之间的关系,用例图仅从参与者使用系统的角度描述系统中的信息。 图例 示例 2. 时序图(顺序图) 顺序图描述了对象以及对象之间传递的消息,强调对象之间的交互是按照时间的先后顺序发生的,这些特定顺序发生的交互序列从开始到结束需要一定的时间。在顺序图中主要包括了以下 4 种元素。 ● 对象 ● 生命线 ● 激活 ● 消息 图例 示例 3. 协作图 协作图与顺序图一样,也是用于描述系统中各对象的交互关系并展现对象间的消息传递,但两者侧重点不同,顺序图着重于描述交互的时间顺序,而协作图着重于描述协作对象间的交互和连接。还可以从另一个角度来看两种图的定义,顺序图是按照时间的顺序布图,而协作图是按照空间来布图。 图例 示例 顺序图与协作图的关系 顺序图和协作图在语义上是等价的,它们之间可以进行互相转换。 例如上面的协作图可以等价转化为顺序图: 4. 类图 类图描述了类和类间关系,它从静态角度来表示一个系统,因此类图属于一种静态图。类图是 UML 建模中最基本和最重要的一类图。 图例 示例 5. 对象图 对象图是类图的实例,几乎使用与类图完全相同的标识。它们的不同点在于对象图显示类的多个对象实例,而不是实际的类。一个对象图是类图的一个实例。由于对象存在生命周期,因此对象图也是有生命周期的,它只能在系统某一时间段存在。 示例 6. 包图 创建包图的主要作用是: 描述需求的高阶概述。 描述设计的高阶概述。 在逻辑上把一个复杂的图模块化。 组织源代码。 对框架进行建模。 图例 示例 7. 状态图 状态图主要用来描述一个特定对象的所有可能状态以及由于各种事件的发生而引起状态之间的转移。通过状态图可以知道一个对象、子系统、系统的各种状态及其收到的消息对其状态的影响。通常创建一个 UML 状态图是为了以下的研究目的:研究类、角色、子系统或构件的复杂行为。 状态图主要由起点、终点和状态组成,各状态由转移连接在一起。状态是对象执行某项活动或等待某个事件时的条件。转换是两个状态之间的关系,它由某个事件触发,然后执行特定的操作或评估并导致特定的结束状态。 状态图适合于描述跨越多个用例的单个对象的行为,而不适合描述多个对象之间的行为协作。为此,常常将状态图与其他技术组合使用。 图例 示例 8. 活动图 活动图是用来描述达到一个目标所实施一系列活动的过程,描述了系统的动态特征。活动图类似结构化程序课程中的流程图,不同之处在于它支持并行活动。活动图和状态图的主要区别在于状态图侧重从行为的结果来描述,以状态为中心;活动图侧重从行为的动作来描述,以活动为中心。活动图用来为一个过程中的活动序列建模,而状态图用来为对象生命期中的各离散状态建模。 图例 示例 9. 构件图 构件是系统的模块化部分,它封装了自己的内容,且它的声明在其环境中是可以替换的;构件利用提供接口和请求接口定义自身的行为,它起类型的作用。 图例 示例...

December 26, 2021 · 1 min · 李昌

Tutorial for Beginner

逛GitHub的时候无意中发现微软有一个Web-Dev-For-Beginners的库,然后随手搜了一下,发现还有很多类似的,这里纪录一下其中比较好的,有备无患。 可以Google搜索Beginners site:github.com/microsoft查看相关的信息 1. Web-Dev-For-Beginners web开发课程,一共12周,24节课,每节课都包括课前和课后测验、完成课程的书面说明、解决方案、作业等。源文件为英文版,但每个章节都配备有不同语言的翻译版。同时也提供pdf版本下载。 项目地址:https://github.com/microsoft/Web-Dev-For-Beginners 2. ML-For-Beginners 机器学习课程,12周,26节课。主要使用sklearn库。 项目地址:https://github.com/microsoft/Data-Science-For-Beginners 3. Data-Science-For-Beginners 数据科学课程,10周,20节课。每节课包括课前和课后测验、完成课程的书面说明、解决方案和作业。 项目地址:https://github.com/microsoft/Data-Science-For-Beginners 4. IoT-For-Beginners 物联网开发课程,12周,24节课。每节课都包括课前和课后测验、完成课程的书面说明、解决方案、作业等。 项目地址:https://github.com/microsoft/IoT-For-Beginners 5. beginners-intro-javascript-node nodejs课程 项目地址:https://github.com/microsoft/beginners-intro-javascript-node 6. beginners-series-rust rust课程。这个项目感觉还不是太完善,但依然可以作为参考。 项目地址:https://github.com/microsoft/beginners-series-rust 7. beginners-django django课程。这个项目就厉害了,啥也没有,不过创建时间还短,先插个眼。 项目地址:https://github.com/microsoft/beginners-django

December 24, 2021 · 1 min · 李昌