dream

一个菜鸟程序员的成长历程

0%

数据库系统原理第一节

数据

什么是数据?

数据是描述事物的符号记录,是指利用物理符号记录下来的,可以鉴别的信息

数据是信息存在的一种形式,只有通过解释或处理的数据才能成为有用的信息。

什么是数据库?

数据库是指长期储存在计算机中的有组织的,可共享的数据集合。

数据要按照一定的数据模型组织描述和存储,具有较小的冗余度,较高的数据独立性,系统易于扩展,并可以被多个用户分享.

数据库的三个特点:

  • 永久存储
  • 有组织
  • 可共享

数据库管理系统(DBMS)

数据库管理系统 是专门用于建立管理数据库的一套软件,介于应用程序操作系统之间

1.数据定义功能
2.数据操纵功能
3.数据库的运行管理功能
4.数据库的建立和维护功能
5.数据组织,存储和管理功能
6.其他功能

数据库系统

组成:

  • 用户
  • 数据库管理系统
  • 数据库
  • 数据库管理员
  • 应用程序

数据库管理技术的发展

  • 人工管理阶段
    1. 数据不保存
    2. 应用程序管理数据
    3. 数据面向应用程序
  • 文件系统阶段
    把数据变成文件存在磁盘
    优点:物理数据独立性
  • 数据库系统阶段
    1. 数据集成(主要目的)
    2. 数据共享性(高)
    3. 数据冗余(小)
    4. 数据一致性
    5. 数据独立性高
    6. 实施统一管理与控制

数据库系统的结构

数据库系统结构的分类

用户视角

  • CS结构
  • BS结构

DBA视角

内部系统结构

采用三级模式

  • 模式 也称为概念模式逻辑模式 概念视图,数据库的核心,数据库设计的关键
  • 内模式 存储模式物理模式 内部视图或存储视图
  • 外模式 给应用使用,不是唯一的,也称为子模式用户模式数据视图即用户视图
外部系统结构
  • 集中式结构
  • 分布式结构
  • 并行结构

三级模式结构的两层映像与数据独立性

所谓映像,就是一种对应规则,它指出映像双方是如何进行转换的。

模式 - 内模式映像:保证了数据与程序的物理独立性

外模式 - 模式映像:保证了数据与程序的逻辑独立性

OpenResty的安装

wsl 使用的是ubuntu 20的版本,所以可以直接使用apt进行安装,OpenResty官网的安装也是推荐使用的apt进行安装。

添加openresty的公钥

1
sudo apt-get -y install --no-install-recommends wget gnupg ca-certificates

导入 GPG 秘钥

1
wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -

添加 Openresty 的源

1
2
echo "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main" > openresty.list
sudo cp openresty.list /etc/apt/sources.list.d/

更新apt

1
sudo apt-get update

安装openresty

1
sudo apt-get -y install --no-install-recommends openresty

检查版本确认是否安装成功

1
openresty -V

启动 openresty

1
sudo service openresty start

访问 localhost 查看

1
curl localhost

安装 resty 命令

1
sudo apt-get -y install openresty-resty

执行 hello world看看是否安装成功

1
resty -e 'print("Hello Resty")'

安装 resty-doc

1
sudo apt-get -y install openresty-restydoc

OpenResty的目录介绍和helloworld

安装目录介绍

上文提到是 ubuntu apt 安装的 openresty

可以查看安装目录

1
openresty -V

安装目录是/usr/local/openresty

目录:

  • bin 这个目录里面是可执行文件,比如openresty,resty,restydoc这些程序
  • pod 这个目录存放的是openresty的文档
  • nginx 存放的就是nginx得相关文件
  • luajit 存放的luajit的相关文件
  • lualib 这个目录放的是lua库,主要分为 ngx 和 resty 两个子目录
    • ngx 存放 lua-resty-core 这个官方项目中的lua代码,里面都是基于FFI重新实现的 openresty API
    • resty 存放各种 lua-resty-* 项目包含的lua代码

wsl安装docker

wsl 使用的是ubuntu 20的版本,所以可以直接使用apt进行安装,docker官网的安装也是推荐使用的apt进行安装。

需要先更新apt安装包

1
sudo apt-get update

安装一些依赖

1
2
3
4
5
6
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release

添加Docker官方的GPG密钥:

1
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

添加docker的源

1
2
3
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

更新apt安装包

1
sudo apt-get update

安装docker

1
sudo apt-get install docker-ce docker-ce-cli containerd.io

安装完成后启动docker

1
sudo service docker start

测试,运行hello world

1
sudo docker run hello-world

index template

index template

index template 可以帮助你设定 Mappings 和 Settins ,并按照一定的规则,自动匹配到新创建的索引上

  • 模板仅在一个索引被新创建时,才会产生作用。修改模板不会影响已经创建的索引
  • 可以设定多个索引模板,这些设置会根据一定的规则 合并到一起
  • 可以指定 Order的数值 控制 合并 的过程

实例

1
2
3
4
5
6
7
8
9
10
PUT _template/template_default
{
"index_patterns":["*"],
"order": 0,
"version": 1,
"settings":{
"number_of_shards":1,
"number_of_replicas":1
}
}

index templalte 的工作方式

当一个新索引被创建

  • 应用 ES 的默认 settins 和 mappings
  • 应用 order 数值低的 index template 的 settings mappings
  • 应用 order 数值高的 index template 的 settings mappings
  • 应用 用户 自定义的 settings mappings

Dynamic template

根据 ES 识别的数据类型,结合字段名称,来动态设定字段类型

  • 所有的字符串类型都设定成 keyword 或者关闭 keyword 字段
  • is 开头的字段都设置成 boolean
  • long_ 开头的都设置成 long 类型

Aggregation 聚合

ES 除了搜索以外提供了统计分析的功能

  • 实时性高
  • Hadoop

通过聚合可以得到数据的概览,是分析和总结全套的数据,而不是寻找单个文档

高性能,只需要一条语句,就可以从 ES 得到结果

  • 无需在客户端自己去实现分析逻辑

比如 Kibana 中的可视化报表就是使用 聚合 实现的

分类

Bucket Aggregation : 一些满足特定条件的集合,相当于 sql 里面的 group by 分组功能

Metric Aggregatino : 提供数学运算,比如最大值,最小值,平均值 相当于 sql 里面的 count(),max()等函数功能

Pipeline Aggregation: 可以二次聚合

Matrix Aggregation: 支持对多个字段的操作并提供一个结果矩阵

极客时间 ES 学习笔记

自定义Analyzer

多字段特性

实现精确匹配

  • 增加一个 keyword 字段

使用不同的analyzer

  • 不同语言
  • pinyin 字段的搜索
  • 还支持为 搜索 和 索引 指定不同的 analyzer

Exact Values vs Full Text

Exact Value 包括数字 / 日期 / 具体一个字符串(例如 Apple Store) 精确值 不需要分词

  • ES 中的 keyword

全文本,非结构化的文本数据 需要分词

  • ES 中的 text

自定义分词

当 ES 自带的分词器无法满足时,可以自定义分词器。通过自己组合不同的组件实现

  • Character Filter

  • Tokenizer

  • Token Filter

通过自己组合上面不同的组件,可以实现出不同的分词器效果。

Character Filter

在 Tokenizer 之前对文本进行处理。可以配置多个进行不同的文本处理。会影响 Tokenizer 的 position 和 offset 信息

下面是一些自带的 Character Filter

  • HTML strip 去除 html 标签
  • Mapping 字符串替换
  • Pattern replace 正则匹配替换

Tokenizer

将原始的文本按照一定的规则,切分为词

下面是一些ES内置的 Tokenizer

  • whitespace
  • standard
  • uax_url_email
  • pattern
  • keyword
  • path hierarchy

也可以用 JAVA 开发插件,实现自己的 Tokenizer

Token filter

将 Tokenizer 输出的单词 进行增加修改删除等操作

下面是ES 自带的

  • Lowercase 小写
  • stop 停止词
  • synonym 近义词

这几个操作简单来说就是

  • Character Filter 在分词前进行处理
  • Tokenizer 分词
  • Token Filter 分词后进行处理

自定义分词器

指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
PUT test_home
{
"settings":{
"analysis":{
"analyzer":{
my_analyzer:{ //自定义分词器
"type":"custom",
"char_filter":[
"test" //自定义 character filter
],
"tokenizer":"test_tokenizer", //自定义 tokenizer
"filter":[ //token filter
"lowercase",
"english_stop"
]
},
"tokenizer":{ //自定义 tokenizer
"test_tokenizer":{
"type":"pattern",
"pattern":"[?]"
}
},
"char_filter":{ //自定义 character filter -替换成_
"test":{
"type":"mapping",
"mappings":[
"-" => "_"
]
}
},
"filter":{ //设置 停止词
"english_stop":{
"type":"stop",
"stopwords":"_englsh_"
}
}
}
}
}
}

极客时间 ES 学习笔记

Analyzer分词

Analysis 和 Analyzer

Analysis - 文本分析是把全文本转换成一系列单词(term/token)的过程,也叫分词

Analysis 是通过 Analyzer 来实现的

  • 可使用 Elasticsearch 内置的分析器,或者按需制定分析器

除了在数据写入时转换词条,匹配 Query 语句时候也需要用相同的分析器对查询语句进行分析

Analyzer 的组成

分词器是专门处理分词的组件,由三部分组成

  • Character Filters (针对原始文本处理,例如去除html)
  • Tokenizer (按照规则切分为单词)
  • Token Filter(将切分的单词进行加工,小写,删除 stopwords,增加同义词)

例子:

Mastering Elasticsearch & Elasticsearch in Action 经过上面的步骤就会产生

  • master
  • elasticsearch
  • action

ES的内置分词器

  • Standard Analyzer - 默认分词器,按词切分,小写处理
  • Simple Analyzer - 按照非字母切分(符号被过滤),小写处理
  • Stop Analyzer - 小写处理,停用词过滤(the a is)
  • WhiteSpace Analyzer - 按照空格切分,不转小写
  • Keyword Analyzer - 不分词,直接将输入当做输出
  • Patter Analyzer - 正则表达式,默认\W+(非字符分隔)
  • Language - 提供了30多种常见语言的分词器
  • Customer Analyzer 自定义分词器

使用 _analyzer API

直接指定 Analyzer 进行测试

指令

1
2
3
4
5
GET /_analyze
{
"analyzer":"standard",
"text":"Mastering Elasticsearch & Elasticsearch in Action"
}

结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{
"tokens" : [
{
"token" : "mastering",
"start_offset" : 0,
"end_offset" : 9,
"type" : "<ALPHANUM>",
"position" : 0
},
{
"token" : "elasticsearch",
"start_offset" : 10,
"end_offset" : 23,
"type" : "<ALPHANUM>",
"position" : 1
},
{
"token" : "elasticsearch",
"start_offset" : 25,
"end_offset" : 38,
"type" : "<ALPHANUM>",
"position" : 2
},
{
"token" : "in",
"start_offset" : 39,
"end_offset" : 41,
"type" : "<ALPHANUM>",
"position" : 3
},
{
"token" : "action",
"start_offset" : 42,
"end_offset" : 48,
"type" : "<ALPHANUM>",
"position" : 4
}
]
}

指定索引的字段进行测试

指令

1
2
3
4
5
POST test_home/_analyze
{
"field": "job_name",
"text":"Mastering Elasticsearch, Elasticsearch in Action"
}

结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{
"tokens" : [
{
"token" : "mastering",
"start_offset" : 0,
"end_offset" : 9,
"type" : "<ALPHANUM>",
"position" : 0
},
{
"token" : "elasticsearch",
"start_offset" : 10,
"end_offset" : 23,
"type" : "<ALPHANUM>",
"position" : 1
},
{
"token" : "elasticsearch",
"start_offset" : 25,
"end_offset" : 38,
"type" : "<ALPHANUM>",
"position" : 2
},
{
"token" : "in",
"start_offset" : 39,
"end_offset" : 41,
"type" : "<ALPHANUM>",
"position" : 3
},
{
"token" : "action",
"start_offset" : 42,
"end_offset" : 48,
"type" : "<ALPHANUM>",
"position" : 4
}
]
}

自定义分词进行测试

指令

1
2
3
4
5
6
POST _analyze
{
"tokenizer": "standard",
"filter": ["lowercase"],
"text":"Mastering Elasticsearch, Elasticsearch in Action"
}

结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{
"tokens" : [
{
"token" : "mastering",
"start_offset" : 0,
"end_offset" : 9,
"type" : "<ALPHANUM>",
"position" : 0
},
{
"token" : "elasticsearch",
"start_offset" : 10,
"end_offset" : 23,
"type" : "<ALPHANUM>",
"position" : 1
},
{
"token" : "elasticsearch",
"start_offset" : 25,
"end_offset" : 38,
"type" : "<ALPHANUM>",
"position" : 2
},
{
"token" : "in",
"start_offset" : 39,
"end_offset" : 41,
"type" : "<ALPHANUM>",
"position" : 3
},
{
"token" : "action",
"start_offset" : 42,
"end_offset" : 48,
"type" : "<ALPHANUM>",
"position" : 4
}
]
}

中文分词的难点

中文句子,切分成一个个词(不是一个个字)

英文字,单词有自然地空格进行切分

一句中文,在不同的上下文,有不同的理解

推荐的一些中文分词器:

极客时间 ES 学习笔记

Dynamic Mapping和常见字段类型

Mapping

Mapping 类似数据库中的 schema的定义,作用如下:

  • 定义索引中的字段的名称
  • 定义字段的数据类型,例如字符串,数字,布尔等
  • 字段,倒排索引的相关配置

Mapping 会把 JSON 文档映射成 Lucene 所需要的扁平格式

一个Mapping 属于一个索引的 Type

  • 每个文档都属于一个Type
  • 一个 Type 有一个 Mapping 定义
  • 7.0开始,不需要在 Mapping 定义中指定 Type信息

字段的数据类型

简单类型
  • Text/Keyword
  • Date
  • Interger/Floating
  • Boolean
  • IPv4 & IPv6
复杂类型
  • 对象类型
  • 嵌套类型
特殊类型

geo 是用于存储地理位置信息的类型

  • geo_point & geo_shape/ percolator

Dynamic Mapping

这个就是动态的Mapping,可以不需要手动指定,由 ES 动态识别数据类型,来生成对应的Mapping。

但是这样生成的 Mappping 不一定正确。

如果想要修改Mapping

  • 新增加字段
    • Dynamic 设为 true,一旦有新字段,Mapping会自动更新
    • Dynamic 设为 false,一旦有新字段,Mapping不会更新,新增加的字段无法被索引,但是_source里面有数据
    • Dynamic 设为 Strict,文档写入失败
  • 已有字段,一旦已经有数据就不支持修改了
    • Lucene实现的倒排索引,一旦生成就不能修改
  • 如果想要修改,需要Reindex API ,重建索引

原因:

  • 如果修改了字段的数据类型,会导致已被索引的数据无法被搜索
  • 但是如果是增加新的字段,就不会有这种情况

注意!!!:
如果Dynamic设为false,那么新增字段无法被索引,也就意味着不能拿这个字段去搜索,比如新增加一个name字段,那么无法搜索name这个字段,比如你想搜索name是张三的,是搜索不出来的。

极客时间 ES 学习笔记

RequestBody和Query DSL简介

通过RequestBody 实现搜索

参数:

  • q:指定查询语句,使用Query String Syntax
  • df:默认字段,不指定会对所有字段进行查询
  • sort:排序
  • from/size: 用来分页
  • Profile 可以查看查询是如何被执行的

这个方法的参数和URI是一样的,比如我们在kibana里面执行下面的指令:

1
2
3
4
5
6
7
GET test_home/_search
{
"profile": "true",
"from":0,
"size":10,
"sort":[{"id":"desc"}]
}

查询指定字段

这种方式还可以查询指定字段,通过_source参数来指定。支持通配符

指令

1
2
3
4
5
6
7
8
GET test_home/_search
{
"profile": "true",
"query":{
"match_all":{}
},
"_source":['job_name','id'] //指定字段
}

脚本字段

可以进行一些简单运算,拼接字符串等操作

指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GET test_home/_search
{
"profile": "true",
"query":{
"match_all":{}
},
"script_fields":{
"new_field":{
"script":{
"lang":"painless" //使用这个脚本
"source": "doc['job_name'].value+'_hello'" //在职位名称后面拼接_hello
}
}
}
}

结果

1
2
3
4
5
"fields":{
"new_fields":[
"产品_hello"
]
}

query DSL

通过DSL查询产品怎么办呢,可以使用query参数

1
2
3
4
5
6
7
8
9
10
GET test_home/_search
{
"profile": "true",
"query":{
"match":{ //使用match 而不是 match_all
"job_name":"产品" //这里就相当于出现产 或者 品 都会搜出来 左边的 job_name 就是搜索的字段
}
},
"_source":['job_name','id'] //指定字段
}

如果想使用AND可以增加参数,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
GET test_home/_search
{
"profile": "true",
"query":{
"match":{ //使用match 而不是 match_all
"job_name": { //这里变成一个对象 左边的 job_name 就是搜索的字段
"query":"产品", //这里是搜索内容
"operator":"AND" //这里指定AND OR NOT
}
}
},
"_source":['job_name','id'] //指定字段
}

短语搜索 match phrase

这里就是短语,单词搜索,等价于URI的phrase search

指令

1
2
3
4
5
6
7
8
9
10
11
12
13
GET test_home/_search
{
"profile": "true",
"query":{
"match_phrase":{ //使用match_phrase
"job_name": { //这里变成一个对象 左边的 job_name 就是搜索的字段
"query":"产品", //这里是搜索内容
"slop":1, //代表可以有一个错误
}
}
},
"_source":['job_name','id'] //指定字段
}

极客时间 ES 学习笔记

Search API

两种方法

URI Search

  • 通过Url参数来进行查询

url指定参数q=field:搜索内容

例子:
http://localhost:9200/{index}/_search?q={field}:搜索内容

url:
http://localhost:9200/test_home/_search?q=job_name:php

Request Body Search

  • 通过ES提供的JSON格式的DSL语句进行查询
语法 范围
/_search 集群上所有索引
/{index}/_search 对应index上的数据
/{index},{index}/_search 对应多个index上的数据
/test*/_search 所有test开头的index上的数据

支持GET POST两种方式

例子:

1
2
3
4
5
6
GET/POST test_home/_search
{
"query":{
"match_all": {}
}
}

搜索返回的结果

  • took: 查询花的时间
  • hits-total: 符合条件的总文档数
  • hints: 结果集
  • _score: 相关度评分

相关度

Infomation Retrieval

  • Precision(查准率) - 尽可能返回较少的无关文档
  • Recall (查全率) - 尽量返回较多的相关文档
  • Ranking - 是否能按相关度进行排序

极客时间 ES 学习笔记