Catalyst 优化器

结构

Catalyst优化器:利用Scala模式匹配和quasiquotes机制构建的 可扩展查询优化器

sparksql_optimization

sparksql_procedure

  • SparkSQL Pipeline的中间核心部分

Parser模块

Parser模块:将SQL语句切分为token,根据一定语义规则解析为AST

sql_parser_ast

  • Spark1.x使用Scala原生Parser Combinator构建的词法、语法 分析器

  • Spark2.x使用采用第三方语法解析器工具ANTLR4

    • ANTLR4根据语法文件SqlBase.g4自动解析生成两个Java类 ,将sql语句解析成ParseTree的语法结构

      • SqlBaseLexer:词法解析器
      • SqlBaseParser:语法解析器
    • 随后ParsePlan过程,使用AstBuilder.scala将ParseTree 转换为catalyst表达式逻辑计划Unresovled Logical Plan

      • Unsolved Relation
      • Unsolved Function
      • Unsolved Attribute

Analyzer模块

Analyzer模块:使用Analysis Rules,借助数据元数据 (session cataloghive metastore)将ULP解析为 Logical Plan

sparksql_catalyst_analyzer

  • ULP虽然具备基本骨架,但是系统对表的字段信息不清楚,需要 基本元数据信息表达ULP中token

  • 遍历整个AST,对树上每个结点进行数据类型绑定、函数绑定, 得到LP

Schema Catalog

元数据信息:表的模式信息

  • 表的基本定义:表名、列名、数据类型
  • 表的数据格式:json、text、parquet、压缩格式
  • 表的物理位置

Optimizer模块

Optimizer模块:使用Optimization Rules对LP进行合并、列 裁剪、过滤器下推等优化工作,生成等价Optimized Logical Plan

  • 分为RBO、CBO两种优化策略,是catalyst核心

Spark Planner

Spark Planner模块:将OLP转换为spark能够理解的 Physical Plan

sql_optimization_physical_plan

  • 将逻辑上可行的执行计划变为Spark真正可以执行的物理计划
  • 物理计划实际上是逻辑计划中耗时最小的算法实现

Join

Join类型

SparkSQL目前支持三种join算符

  • shuffle hash join
  • broadcast hash join
  • sort merge join

Broadcast Hash Join

broadcast hash join:将小表广播分发到大表所在的结点上, 并行在各节点上进行hash join

sparksql_broadcast_hash_join

  • 适合小表很小,可以直接广播的场合

    • spark.sql.autoBroadcastJoinThreshold设置广播小表 大小上限
  • broadcast阶段:将所小表广播分发到大表所在的所有主机

    • driver分发
    • p2p分发
  • hash join结点:各结点独立并行hash join

    • 小表构建hash表
    • 各结点本地大表试探

Shuffle Hash Join

shuffle hash join:按照join key分区,在每个结点独立并行 进行hash join

sparksql_shuffle_hash_join

  • 类似分布式GHJ,不同块位于不同结点

  • shuffle阶段:将表按照join key分区,将具有相同join key 的记录重分布到同一结点

  • hash jon阶段:各结点使用本地数据独立并行hash join

Sort Merge Join

SMJ:按照join key分区,在各节点独立并行SMJ

sparksql_sort_merge_join

  • shuffle阶段:将表按照join key分区,将具有相同join key 的记录重分布到同一结点

  • sort阶段:各节点并行对本地数据排序

    • spark当前shuffle算法使用sort-based shuffle算法
    • 理论上shuffle过后各分区数据已经排序完毕,无需再次 sort,效率很高
  • merge阶段:各节点对排序好表数据执行join操作

Join Reorder

  • 基于CBO的join重排序优化:用统计信息预估的基修正join顺序

  • 使用动态规划算法,考虑所有可能组合,选择代价最小的方案

    • 单个join操作成本,join树的成本是所有中间join成本总和

      • carinality:对应CPU成本
      • size:对应IO成本
    • 没有任何join条件同时包含左、右子树时,修剪笛卡尔积 减少搜索范围

Statistics Collection Framework

CBO依赖统计细节信息优化查询计划

  • CBO自下而上遍历LP,统计信息可以随之传播到上层算子

统计信息类型

  • Numeric、Date、Timestamp

    • Distinct Count
    • Max
    • Min
    • Null Count
    • Average Length:定长
    • Max Length:定长
  • String、Binary

    • Distinct Count
    • Null Count
    • Average Length
    • Max Length

统计方式

  • 扫描全表:简单、统计信息准确,代价大
  • 抽样统计:

应用

Filter Selectivity

过滤选择率:估计应用谓词表达式过滤的选择率

逻辑运算符
  • AND:左侧过滤条件选择率、右侧过滤条件选择率之积

  • OR:左侧、右侧过滤条件选择率之和,减去其乘积

  • NOT:1减去原始过滤条件选择率

比较运算符
  • =:等于条件

    • 若常数取值在当前列取值范围之外,则过滤选择率为0
    • 否则根据柱状图、均匀分布得到过滤选择率
  • <:小于条件

    • 若常数取值小于当前列最小值,则过滤选择率为0
    • 否则根据柱状图、均匀分数得到过滤选择率

Join Carinality

联接基:估计联接操作结果的基

  • inner:其他基估计值可由inner join计算

    • num(A):join操作前表A的有效记录数
    • distinct(A.k):表A中列k唯一值数量
  • left-outer:取inner join、左表中基较大者

  • right-outer:取inner join、右表中基较大者

  • full-outer

B)

$$

配置文件笔记

Ini

Toml

Yaml

基本语法规则

  • 大小写敏感
  • 缩进代表层级关系
  • 必须空格缩进
    • 不要求空格数目
    • 同层左对齐

数据结构

  • -:?等符号后总是需要空格
  • #表示注释

对象/映射

对象/映射:键值对集合,:表示、{}行内表示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// `:`后要空格
key: value

// 多层级对象
key:
child_key1: val1
child_key2: val2
// 流式表示
key: {child_key1: val1, child_key2: value2}


// 复杂对象格式:键、值都是数组
// `? `(空格)表示复杂key
?
- complex_key1
- complex_key2
// `: `(空格)表示复杂value
:
- complex_val1
- complex_val2

数组

数组:-开头、[]行内表示

1
2
3
4
5
6
7
8
9
10
11
12
13
// `[[ele1, ele2]]`
-
- ele1
- ele2


// `pkey: [{key1: val1}, {key2: val2, key3: val3}]`
pkey:
-
key1: val1
-
key2: val2
key3: val3

标量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
boolean: 
- TRUE # true, True均可
- FALSE # false, False均可

float:
- 3.14
- 3.14e+2 # 科学计数法

int:
- 13
- 0b1010_1010_1010_1010 #二进制

null:
key: ~ # `~`表示null

string:
- 'hello world' # 单、双引号包括特殊字符
- line1
line2 # 字符串可以拆成多行,换行转换为空格

datetime:
- 2019-07-10 # ISO 8601格式,`yyyy-MM-dd`
- 2019-07-10T17:53:23+08:00 # ISO 8601格式,`<date>T<time>+<timezone>`

特殊符号

  • ---:表示文档开始
  • ...:文档结束
    • 二者配合在文件中记录多个yaml配置项
  • !!:强制类型转换
  • >:折叠换行符为空格
  • |:保留换行符
  • &:锚点
    • 不能独立定义,即非列表、映射值
  • *:锚点引用
    • 可以多次引用
    • 被引用值可能会之后被覆盖
  • <<:合并内容
    • 主要配合锚点使用
    • 相当于unlist解构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---							# 文档开始
string:
- !!str 13
- !!str true
... # 文档结束

---!!set # 强转为set
- A1: &A1 {x: 1, y: 2} # 定义名称为`A1`锚点
- A2: &A2 {a: 3, b: 4} # 定义名称为`A2`锚点
- B: > # 折叠换行符
this line
will collapse
- C: | # 保留换行符
this paragraph
keeps the <CR>
- D: *A` # 引用名为`SS`的锚点
- E: # E等价于`{x:1, y:2, a:34, b:4}`
<<: [*A1, *A2]
a: 34
...

API

  • Java
    • package:org.yaml.snakeyaml.Yaml
  • Python
    • package:PyYaml
    • import yaml

Xml

数据库背景

数据库术语

数据库结构

  • 数据源:多源数据继承
  • 数据仓库继承工具:FTL工具、MapReduce
  • 数据仓库服务器:列存储数据库引擎
  • 数据即使:数据仓库的数据子集、聚集数据继
  • OLAP服务器:提供多维数据视图
  • 前台数据分析工具
    • 报表工具
    • 多维分析工具
    • 数据挖掘工具

数据库类型

  • 传统关系型数据库
  • MPP大规模并行处理数据库
  • NoSQL数据库
  • 图数据库
  • NewSQL数据库
  • GPU数据库

数据查询

  • Project Pushdown:投影下推

    • 只读取、查询需要的
    • 减少每次查询的IO数据量
  • Predicate Pushdown:谓词下推

    • 将过滤条件尽快执行,跳过不满足条件

数据压缩算法

  • Run Length Encoding:重复数据
  • Delta Encoding:有序数据集
  • Dictionary Encoding:小规模数据集合
  • Prefix Encoding:字符串版Delta Encoding

数据库调优

数据库调优:是数据库具有更高的吞吐量、更快响应

  • 被调优对象是数据库整体
  • 需要考虑很多资源、数据库配置

人工调优

  • 依赖人工,效率低下
  • 要求操作者理解查询原理,对应用、DBMS、操作系统、硬件有 一定理解

基于案例调优

  • 总结典型应用案例情况中数据库参数推荐配置值、逻辑层设计等 情况,为用户调优工作提供参考、借鉴
  • 忽略系统动态性、不同系统之间差异

自调优

  • 为DBMS建立模型,根据“影响数据库性能效率的因素”,自动进行 参数配置
  • 部分商业数据库实现了自调优技术

需求分析期

应用情况估算

  • 应用使用方式
    • 将业务逻辑转换为读写分布逻辑,以读多写少、读写均衡 区分OLAP、OLTP
    • 应用对数据库的并发情况、并发是否可池化
  • 数据量
  • 对数据库压力、峰值压力

系统选型策略

  • 确定适合的数据库:开源、商业;集群、单机
  • 操作系统、中间件、硬件、网络选型

项目设计期

数据模型设计

根据业务逻辑,从以下角度考虑表结构

  • E-R模型设计:遵循E-R模型设计原理,适当非规范化可以改善 系统查询性能
  • 数据逻辑分布策略:减少数据请求中不必要的数据量
    • 分区
    • 利用E-R模型分表
  • 数据物理存储策略:减少IO操作
    • 启用压缩
    • 分开存储索引、表数据
    • 不同表数据分布在不同表空间
    • 不同表空间分布在不同物理存储,尤其是读写量大的表空间 分布在不同物理存储上
    • 日志、索引、数据分布在不同物理存储上
  • 索引:在查询频繁的对象上建立恰当索引

开发期

SQL设计

  • 编写正确、查询效率高的SQL语句,依据“查询重写规则”
    • 有意识地保障SQL能利用到索引

数据库功能启用

  • 查询重用
  • 数据库参数设计

测试、试运行、上线、维护

模型系统预运行

  • 在备用系统上模型实际运行环境,加大压力进行相似测试

系统监控分析

  • 应用系统表示:收集用户使用意见、系统存在问题
  • OS环境监控:实时监控CPU、内存、IO等,对比历史正常情况
  • 数据库内部状态监控:系统表、视图、工具、锁的情况
  • 日志分析:在数据库的日志、操作系统日志中找出异常

HiveSQL

命令行参数

  • -d/--define <key=value>:替换脚本中shell形式变量
  • --hivevar <key=value>:替换脚本中shell形式变量
    • 结合hive脚本中设置shell变量使用
  • -h <hostname>:hive服务器
  • -p <port>:hive服务器端口
  • -database <database>:连接数据库
  • -e <quoted-query-string>:从命令行获取、执行hive脚本
  • -f <filename>:从文件获取、执行hive脚本
  • -i <filename>:初始化hive脚本
  • --hiveconf <property=value>:设置hive参数
  • -S/--slient:安静模式启动交互hive shell
  • -v/--verbose:详细模式
  • -H/--help:帮助

辅助语句

结果输出

  • INSERT INTO/OVERWRITE:查询结果追加/覆盖在hive表中
  • INSERT INTO/OVERWRITE [LOCAL] DIRECTORY:查询结果追加/ 覆盖本地/HDFS目录
  • 有分区情况下,仅覆盖当前分区

内置函数

聚合函数

  • collect_set():配合group by合并、消除重复字段,返回 array
  • concat_ws():连接字符串
  • if(<condition>, <true_value>, <false_value>):判断条件
  • size():返回array长度
  • length():返回字符串大小

配置相关语句

文本分隔符

  • 记录分隔:\n
  • 字段分隔:\001(八进制)ASCII码1字符
  • Array、Struct、Map等集合中元素分隔:\002ASCII码1字符
  • Map中键值对分隔:\003ASCII码1字符
1
2
3
4
line terminated by `\n`
row format delimited fields terminated by `\001`
collection items terminated by `\002`
map keys terminated by `\003`

空值

  • hive中空值一般有两种存储方式

    • NULL:底层存储NULL,查询显示为NULL
    • \N:底层存储\N,查询显示为NULL,查询输出为\N
  • 空值查询:<field> is NULL

    • NULL:也可<field> = 'NULL'
    • \N:也可<field> = '\\N'(转义)
  • 底层存储设置参见表存储
  • 空字符串不是空值,需要用<field> = ''查询

表存储配置

分区

属性

serdeproperties

  • 设置空值存储方式

    1
    alter <table> SET serdeproperites('serialization.null.format' = '\N')

Mysql/Mariadb安装配置

安装

Mysql

大部分系统常用源中包含mysql,直接使用自带的包管理工具安装 即可,对于源中无法找到mysql的系统可以访问官网获取 安装方法

1
$ sudo zypper install mysql-server mysql-client

CentOS7

CentOS7的常用源中即不含mysql,安装mysql则需要添加mysql源, 同样在官网中找到添加方式:

  1. 下载的是RPM源rpm包
  2. $ sudo yum localintall安装后即添加源
  3. 使用yum直接安装mysql,需要注意的是默认情况下只有最新版本 mysql源是enabled,其他版本的需要--enablerepo指定或者 /etc/yum.repo.d下修改文件

Mariadb

mariadb和mysql大部分兼容,添加了一些新的特性,是mysql的一个 开源分支,由mysql的作者维护,避免mysql在被Oracle收购后闭源。

  • 大部分情况下,mariadb可以完全看作是mysql
  • 甚至在某些系统中,mariadb服务有别名mysql
  • mariadb控制台命令也是mysql

配置

配置文件

  • /etc/mysql/my.cnf:mysql主配置文件

    • mysql的此配置文件内包含有具体的配置
    • mariadb此文件中则不包含具体配置,而是导入配置文件
      1
      2
      !includedir /etc/mysql/conf.d/
      !includedir /etc/mysql/mariadb.cond.d/
  • ~/.my.cnf

    • 一般不存在,需要自行建文件,注意需要设置文件权限, 只能root用户可写,否则mysql会忽略此配置文件
    • mysqld服务启动需要root权限,因此~目录下的配置文件 基本不可能影响mysql-server状态,即[server]下的配置 基本是无效的

数据位置

  • 数据库存放数据位置:/var/lib/mysql/db_name/

Mysql-Client

登陆

@todo 一个问题,我安装的mariadb,默认的root用户无法在一般用户账户 登陆,必须sudo才能正常登陆

参数登陆

1
$ mysql -h host -P port -u user -p

mysql不带参数启动则是默认cur_user_name@localhost:3306, 表示使用当前用户名作为用户名登陆,如果该用户设置密码,-p 参数不能省略

文件

1
$ mysql --defaults-file=file_name

文件内容格式类似于配置文件

1
2
3
4
5
[client]
host=
user=
password=
database=(可选)

注意

  • mysql中默认存在一个用户名为空的账户,只要在本地,可以 不用账户、密码登陆mysql,因为这个账号存在,使用新建用户 无法通过密码登陆,需要在
    1
    2
    3
    $ use mysql;
    $ delete from user where User="";
    $ flush privileges;

Mysql交互命令

Show信息类

  • SHOW DATABASES:列出MySQLServer数据库。
  • SHOW TABLES [FROM db_name]:列出数据库数据表。
  • SHOW TABLE STATUS [FROM db_name]:列出数据表及表状态信息。
  • SHOW COLUMNS FROM tbl_name [FROM db_name]:列出资料表字段
    • DESC tbl_name:同
  • SHOW FIELDS FROM tbl_name [FROM db_name]
  • DESCRIBE tbl_name [col_name]
  • SHOW FULL COLUMNS FROM tbl_name [FROM db_name]:列出字段及详情
  • SHOW FULL FIELDS FROM tbl_name [FROM db_name]:列出字段完整属性
  • SHOW INDEX FROM tbl_name [FROM db_name]:列出表索引
  • SHOW STATUS:列出 DB Server 状态
  • SHOW VARIABLES [like pattern]:列出 MySQL 系统环境变量
  • SHOW PROCESSLIST:列出执行命令。
  • SHOW GRANTS FOR user:列出某用户权限

User

  • CREATE USER 'USER_NAME'@'ADDRESS' IDENTIFIED BY 'PASSWORD'

    • IDENTIFIED BY PASSWORD这个语法好像已经被丢弃了
  • SET PASSWORD FOR 'USER_NAME'@'ADDRESS' = PASSWORD('NEW_PWD')

  • SET PASSWORD = PASSWORD('NEW_PWD'):修改当前用户密码

  • GRANT PRIVILEGES ON DB_NAME.TBL_NAME TO 'USER_NAME'@'ADDRESS' [WITH GRANT OPTION]

    • WITH GRANT OPTION:允许用户授权
  • REVOKE PRIVILIEGES ON DB_NAME.TBL_NAME TO 'USER_NAME'@'ADDRES%'

  • DROP 'USER_NAME'@'ADDRESS'

说明

  • revoke和grant中的权限需要一致才能取消相应授权

    • grant select不能通过revoke all取消select
    • grant all也不能通过revoke select取消select
  • 特殊符号

    • %:所有address,也可以是ip部分,如:111.111.111.%
      • 这个其实在sql语句中可以表示任意长度字符串
    • *:所有数据库、表

Priviledges

名称 权限
alter alter table
alter routine alter or drop routines
create create table
create routine create routine
create temporary table create temporary table
create user create, drop, rename users and revoke all privilieges
create view create view
delete delete
drop drop table
execute run stored routines
file select info outfile and load data infile
index create index and drop index
insert insert
lock tables lock tables on tables for which select is granted
process show full processlist
reload use flush
replicati on client ask where slave or master server are
replicati on slave
select select
show databases show databases
show view show view
shutdown use mysqladmin shutdown
super change master, kill, purge master logs,
set global sql statements,    use mysqladmin
debug command, create an extra connection
even reach the maximum amount|

|update|update| |usage|connect without any specific priviliege|

执行Sql脚本

  • shell内执行

    1
    mysql -h host -D db_name -u user -p < file_name.sql;
  • mysql命令行执行

    1
    source file_name.sql;

导入、导出数据

导入数据

  • shell内

  • mysql命令行内

    1
    2
    3
    4
    5
    load data [local] infile '/path/to/file' into table tbl_name
    fields terminated by 'sep_char'
    optionally enclosed by 'closure_char'
    escaped by 'esc_char'
    lines terminated by `\r\n`;
    • /path/to/file不是绝对路径,则被认为是相对于当前 数据库存储数据目录的相对路径,而不是当前目录
    • 关键字local表示从客户端主机导入数据,否则从服务器 导入数据

导出数据

  • shell内

  • mysql命令行内

注意:远程登陆mysql时,两种方式导出数据不同,shell导出 数据可以导出至client,而mysql命令行内导出至server

Mysql-Server

数据库字符编码方式

查看

  • 只查看数据库编码方式

    1
    show variables like "character_set_database;
  • 查看数据库相关的编码方式

    1
    show variables like "character%";

    |variable_name|value| |——-|——-| |character_set_client|latin1| |character_set_connection|latin1| |character_set_database|latin1| |character_set_filesystem|binary| |character_set_results|latin1| |character_set_server|latin1| |character_set_system|utf8| |character_sets_dir|/usr/share/mysql/charsets/|

  • 另一种查询数据库编码方式

    1
    show variables like "collation%";

    |Variable_name|Value| |——-|——-| |collation_connection|utf8mb4_general_ci| |collation_database|utf8mb4_general_ci| |collation_server|utf8mb4_general_ci|

相关变量说明

  • character_set_client:客户端编码方式
  • character_set_connection:建立连接是所用编码
  • character_set_database:数据库编码
  • character_set_results:结果集编码
  • character_set_server:服务器编码

保证以上编码方式相同则不会出现乱码问题,还需要注意其他连接 数据库的方式不一定同此编码方式,可能需要额外指定

修改编码方式

修改数据库默认编码方式

修改mysql配置文件(/etc/mysql/my.cnf

#todo
mysql配置文件的优先级
utf8mb4意义
1
2
3
4
5
[client]
default-character-set=utf8mb4
[mysqld]
default-character-set=utf8mb4
init_connect="SET NAMES utf8mb4"

重启mysql即可

修改单个数据库
  • 创建时
    1
    create database db_name character set utf8 collate utf8_general_ci;
    1
    create database if not exists db_name defualt charater set utf8;
脚本、窗口
1
set names gbk;

只修改character_set_clientcharacter_set_connectioncharacter_set_results编码方式,且只对当前窗口、脚本有效, 不影响数据库底层编码方式

SQL语法

基本操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SELECT			<field>, DISTINCT <field>
INTO <new_tbl> [IN <other_db>]
FROM <tbl>
WHERE <field> <OP> <value>/<field>
ORDER BY <field> [ASC/DESC];

INSERT INTO <tbl>[<field>]
VALUES (<value>);

UPDATE <tbl>
SET <field> = <value>
WHERE <field> <OP> <value>/<field>;

DELETE
FROM <tbl>
WHERE <field> <OP> <value>/<field>;

数据库、表、索引、视图

创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
!-- 创建数据库
CREATE DATABASE <db_name>;

!-- 创建表
CREATE TABLE <tbl>(
<field> <dtype>,
<field> <dtype> <CSTRT>, !-- MSSQL、ORACLE
<CSTRT> (<field>,), !-- MySQL
CONSTRAINT [<cstrt_name>] <cstrt> (<field>,) !-- common
)

!-- 创建索引
CREATE INDEX <index_name>
ON <tbl> (<field>);

!-- 创建视图
CREATE VIEW <view_name> AS
<select_expr>;
自增字段
1
2
3
4
5
6
7
8
9
10
!-- MSSQL
<field> <dtype> IDENTITY
!-- MySQL
<field> <dtype> AUTO_INCREMENT
!-- ORACLE:创建自增序列,调用`.nextval`方法获取下个自增值
CREATE SEQUENCE <seq>
MINVALUE <min>
START WITH <value>
INCREMENT BY <step>
CACHE <cache> !-- 提高性能

丢弃

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
!-- 丢弃索引
!-- MSSQL
DROP INDEX <tbl>.<index_name>;
!-- ORACLE
DROP INDEX <index_name>;
!-- MySQL
ALTER TABLE <tbl>
DROP INDEX <index_name>;

!-- 丢弃表/数据
DROP TABLE <tbl>;
TRUNCATE TABLE <tbl>;

!-- 丢弃数据库
DROP DATABASE <db_name>;

!-- 丢弃视图
DROP VIEW <view>;

修改表

1
2
3
4
5
6
7
8
9
10
11
!-- 添加列
ALTER TABLE <tbl>
ADD <field> <dtype>;

!-- 删除列
ALTER TABLE <tbl>
DROP COLUMN <field>;

!-- 修改类型
ALTER TABLE <tbl>
ALTER COLUMN <field> <dtype>;

关键字

TOP

  • MSSQL:SELECT TOP <num>/<num> PERCENT *
  • MYSQL:LIMIT <num>
  • ORACLE:WHERE ROWNUM <= <num>

Alias

  • AS:指定行、列别名

Join

  • [INNER] JOIN
  • LEFT JOIN
  • RIGHT JOIN
  • FULL JOIN

Union

  • UNION:合并SELECT结果集
    • 要求结果集中列数量、类型必须相同

NULL

  • IS [NOT] NULL:比较是否为NULL
  • 比较符无法测试NULL

符号

运算符

  • =:有些方言可以使用==
  • <>:有些方言可以使用!=
  • >
  • <
  • >=
  • <=
  • BETWEEN <value> AND <value>
  • [NOT] IN (<value>)
  • [NOT] LIKE <pattern>
    • %:匹配0个、多个字符
    • _:匹配一个字符
    • [<char>]:字符列中任意字符
    • ^[<char>]/[!<char>]:非字符列中任意字符

逻辑运算

  • AND
  • OR

符号

  • ':SQL中使用单引号包括文本值
    • 大部分方言也支持"双引号

数据类型

MySQL

TEXT类型 描述
CHAR([<size>])
VARCHAR([<size>])
TINYTEXT
LONGTEXT
MEDIUMITEXT
BLOB
MEDIUMBLOB
LONGBLOB
ENUM(<val_list>)
SET
NUMBER类型 描述
TINYINT([<size>])
SMALLINT([<size>])
MEDIUMINT([<size>])
INT([<size>])
BIGINT([<size>])
FLOAT([<size>])
DOUBLE([<size>])
DECIMAL([<size>])
DATE类型 描述
DATE()
DATETIME()
TIMSTAMP()
TIME()
YEAR()

MSSQL

ASCII类型 描述
CHAR([<size>])
VARCHAR([<size>])
TEXT
UNICODE类型 描述
CHAR([<size>])
VARCHAR([<size>])
text
BINARY类型 描述
bit
binary([<n>])
varbinary([<n>])
image
NUMBER类型 描述
TINYINT
SMALLINT
MEDIUMINT
INT
BIGINT
DECIMAL(p, s)
FLOAT([<n>])
REAL
SMALLMONEY
MONEY
DATE类型 描述
DATETIME
DATETIME2
SMALLDATETIME
DATE
TIME
DATETIMEOFFSET
TIMESTAMP

约束

  • 建表时添加约束

    • MSSQL、ORACLE:可直接在字段声明后添加约束
    • MySQL:需独立指定约束
  • 向已有表添加约束

    • 可以添加匿名、具名约束
    • MSSQL、ORACLE:有COLUMN关键字
  • 删除约束

    • MySQL:使用约束关键字指定
    • MSSQL、ORACLE:使用CONSTRAINT关键字指定

NOT NULL

1
<field> <dtype> NOT NULL

DEFAULT

DEFAULT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
!-- 建表
<field> <dtype> DEFAULT <value>

!-- 已有表添加
!-- MySQL
ALTER TABLE <tbl>
ALTER <field> SET DEFAULT <value>;
!-- MSSQL、ORACLE
ALTER TABLE <tbl>
ALTER COLUMN <field> SET DEFAULT <value>;

!-- 删除
!-- MySQL
ALTER TABLE <tbl>
ALTER <field> DROP DEFAULT;
!-- MSSQL、ORACLE
ALTER TABLE <tbl>
ALTER COLUMN <field> DROP DEFAULT;

UNIQUE

UNIQUE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
!-- 建表
!-- MySQL、MSSQL、ORACLE
CONSTRAINT [<cstrt_name>] UNIQUE (<field>,)
!-- MySQL
UNIQUE [KEY] [<cstrt_name>] (<field>)
!-- MSSQL、ORACLE
<field> <dtype> UNIQUE

!-- 已有表添加
!-- MySQL、MSSQL、ORACLE
ALTER TABLE <tbl>
ADD UNIQUE(<field>);
ALTER TABLE <tbl>
ADD CONSTRAINT <cstrt_name> UNIQUE(<field>,);

!-- 删除
!-- MySQL
ALTER TABLE <tbl>
DROP INDEX <cstrt_name>;
!-- MSSQL、ORACLE
ALTER TABlE <tbl>
DROP CONSTRAINT <cstrt_name>;

PRIMARY KEY

PRIMARY KEY

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
!-- 建表
!-- MySQL、MSSQL、ORACLE
CONSTRAINT [<cstrt_name>] PRIMARY KEY (<field>,)
!-- MYSQL
PRIMARY KEY (<field>,)
!-- MSSQL、ORACLE
<field> <dtype> PRIMARY KEY


!-- 已有表添加
!-- MySQL、MSSQL、ORACLE
ALTER TABLE <tbl>
ADD PRIMARY KEY (<field>,);
ALTER TABLE <tbl>
ADD CONSTRAINT <cstrt_name> PRIMARY KEY (<field>,);

!-- 删除
!-- MySQL
ALTER TABLE <tbl>
DROP PRIMARY KEY;
!-- MSSQL、ORACLE
ALTER TABLE <tbl>
DROP CONSTRAINT <cstrt_name>;

FOREIGN KEY

FOREIGN KEY

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
!-- 建表
!-- MySQL、MSSQL、ORACLE
CONSTRAINT [<cstrt_name>] FOREIGN KEY (<field>,)
REFERENCES <tbl>(<field>,)
!-- MYSQL
FOREIGN KEY (<field>,)
REFERENCES <tbl>(<field>,)
!-- MSSQL、ORACLE
<field> <dtype> FOREIGN KEY
REFERENCES <tbl>(<field>,)


!-- 已有表添加
!-- MySQL、MSSQL、ORACLE
ALTER TABLE <tbl>
ADD FOREIGN KEY (<field>,)
REFERENCES <tbl>(<field>,);
ALTER TABLE <tbl>
ADD CONSTRAINT <cstrt_name> FOREIGN KEY (<field>,)
REFERENCES <tbl>(<field>);

!-- 删除
!- MySQL
ALTER TABLE <tbl>
DROP FOREIGN KEY <cstrt_name>;
!-- MSSQL、ORACLE
ALTER TABLE <tbl>
DROP CONSTRAINT <cstrt_name>;

CHECK

CHECK

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
!-- 建表
!-- MySQL、MSSQL、ORACLE
CONSTRAINT [<cstrt_name>] CHECK(<condition>)
!-- MySQL
CHECK (condition)
!-- MSSQL、ORACLE
<field> <dtype> CHECK(<condition>)

!-- 已有表添加
!-- MySQL、MSSQL、ORACLE
ALTER TABLE <tbl>
ADD CHECK (condition);
ALTER TABLE <tbl>
ADD CONSTRAINT <cstrt_name> CHECK (condition);

!-- 删除
!-- MySQL
ALTER TABLE <tbl>
DROP CHECK <cstrt_name>;
!-- MSSQL、ORACLE
ALTER TABLE <tbl>
DROP CONSTRAINT <cstrt_name>;

内建函数

Date

  • MySQL

    • NOW()
    • CURDATE()
    • CURTIME()
    • DATE()
    • EXTRACT()
    • DATE_ADD()
    • DATE_SUB()
    • DATE_DIFF()
    • DATE_FORMAT()
  • MSSQL

    • GETDATE()
    • DATEPART()
    • DATEADD()
    • DATEDIFF()
    • CONVERT()

NULL

  • MSSQL

    • ISNULL(<field>, <replacement>)
  • ORACLE

    • NVL(<field>, <repalcement>)
  • MySQL

    • IFNULL(<field>, <replacement>)
    • COALESCE(<field>, <replacement>)

Aggregate聚集函数

Scalar

Java安装设置

Java 概念

  • Java 平台包括

    • Standard Edition / SE:桌面、简单服务器应用平台
    • Enterprise Edition / EE:在 SE 基础上添加企业级技术标准、模块
      • 包括 JDBCEJB
      • 适合复杂服务器应用
      • Oracle 已停止更新,类似一般模块
    • Micro Edition / ME:手机等小型设备
  • Java 版本号包含小数、整数两种方式

    • SE 平台为例
      • J2SE 1.4 使用小数点后一位标识大版本
      • Java SE 5 后使用整数标识大版本
    • Java 平台对应的 JDK 版本
      • JDK 1.9 使用小数点后一位标识大版本
      • JDK 10 使用整数标识大版本
  • J2 / Java 2 曾经用于标识 Java 版本

Java Virtual Machine

  • JVM:运行java字节码(.class)的虚拟机

    • 无法直接执行.java文件,需要编译为.class
    • java能够跨平台的关键,在所有平台上都有JVM的实现,可以 直接执行编译后的.class文件
  • JVM版本

    • Google dalvik
    • ART
    • Oracle JRE 自带 JVM

Java Runtime Environment

  • JREJava 运行环境,运行 Java 编写的应用
    • JRE = JVM + .class库文件 + 其他支持文件

Java Development Kits

  • JDKJava 开发工具集合
    • JDK = Java 开发工具 + JRE
    • 包括 complierdebugger,用于开发 Java 应用

Java 发行版

  • Java 常见的发行版本两个:OpenJDKJDK
    • JDK(Sun JDK)Sun 公司发布
    • OpenJDKJDK 的开源版本,其实也是Sun公司发布的Java版本,Sun被Oracle收购之后也称为Oracle OpenJDK
      • JDK 的一个“发行版”,Java SE 7 JSR 的一个开源实现
      • 现在同 Oracle JDK 区别很小

        配置

JAVA

1
2
3
4
5
6
7
8
9
export JAVA_HOME=/opt/jdk
# 安装是jdk,所以目录直接由jdk就好
# 或者保留原版本号,创建符号链接`java`执行原目录
# 可自定以部分
export JRE_HOME=$JAVA_HOME/jre
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=$CLASSPATH:$JRE_HOME/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
# jar包是java文件的集合,可以/需要看作是文件夹
# java的`CLASSPATH`所以需要添加的是jar包

Scala

1
2
export SCALA_HOME=/opt/scala
export PATH=$PATH:$SCALA_HOME/bin:$SCALA_HOME/sbin

MAVEN

Git 基础

.gitingore

.gitignore忽略规则

  • !开头:排除应被忽略

  • /结尾:忽略文件夹

  • /开头:git仓库根目录路径开始(可省略)

  • 遵循一定的正则表达式

    • *:多个字符,不包括/,因此多层级目录需要一一指定
    • ?:单个字符
    • []:匹配其中候选字符

.gitignore配置方式

  • 仓库根目录创建.gitignore文件,添加忽略规则

    • 忽略规则针对当前项目
    • .gitignore文件默认随仓库分发,所有人共用忽略规则 (当然可以在.gitignore中配置忽略.gitignore
  • 设置全局忽略文件,对所有git项目适用

    1
    git config --global core.excludesfile /path/to/.gitignore
  • 修改.git/info/exclude文件,添加忽略规则

    • 对单一项目有效
    • 非所有人共用忽略规则

Git配置/config

  • 配置文件、配置类型

    • --system:系统全局配置,配置文件/etc/gitconfig
    • --global:用户全局配置,配置文件 $HOME/.gitconfig$HOME/.config/git/config
    • --local:局部repo配置,配置文件repo/.git/config
    1
    2
    3
    4
    # 修改`section.key`值(缺省`--local`)
    $ git config [--system|--global|--local] <section>.<key> <value>
    # 删除配置项
    $ git config [--system|--global|--local] --unset <section>.<key>

配置文件常用

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
 # 核心修改
[core]
# 忽略文件权限修改
filemode = false
editor = vim
# 提交、检出时换行符设置
# `input`:提交时转换为`<LF>`、检出时不转换
# `false`:提交、检出均不转换
# `true`:提交时转换为`<LF>`、检出时转换为`<CRLF>`
autocrlf = input
# 是否允许文件混用换行符
# `true`:拒绝提交包含混合换行符文件
# `false`:允许提交包含混合换行符文件
# `warn`:提交包含混合换行符文件时警告
safecrlf = true
[user]
name = xyy15926
email = xyy15926@163.com
# 设置别名
[alias]
st = status
ci = commit
br = branch
lg = "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
d = difftool
# 输出着色
[color]
# 打开所有默认终端着色
ui = true
[diff]
tool = vimdiff
[difftool]
prompt = false
  • autocrlf在linux若设置为input,在add包含<CRLF> 文件会报fatal
    • 因为input在提交时会将<CRLF>转换为<LF>,但在 检出时无操作
    • 所以导致即使add也不能保证repo当前状态和提交状态 一致

remote

1
2
3
4
 # 查看远程仓库
$ git remote -v
# 设置远程仓库地址
$ git remote set-url <repo_name> <new_url>

指定ssh key

  • git依赖ssh进行存储库认证,无法直接告诉git使用哪个私钥
  • ~/.ssh/config中配置ssh host:git每次使用host代替原 服务器地址

    1
    2
    3
    4
    host <host>
    HostName github.com
    IdentityFile $HOME/.ssh/id_rsa_github_private
    User git
    • ssh host详见*linux/shell/config_files”
  • GIT_SSH_COMMAND环境变量:指定ssh命令-i中参数

    1
    2
    3
    4
    5
    GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_github_private" git clone ...
    // 可以`export`持久化
    export GIT_SSH_COMMAND = ...
    // 写入git配置
    git config core.sshCommand "..."

展示命令

log

1
2
$ git log [<file_name>]
# 查看文件提交历史

show

1
2
$ git show <tag_no|commit_hash>
# 查看改动内容

语言设计

编程范型

Functional Programming

函数式编程:使用纯函数

  • 程序使用紧密的函数调用表示,这些函数可以进行必要计算, 但是不会执行会改变程序状态(如:赋值)的操作
  • 函数就是数据值,可以像对待其他数据值一样对其进行操作

纯函数

纯函数:没有副作用、表达式对所有引用透明度表达式也是引用透明 的函数

  • 执行过程中除了根据输入参数给出运算结果外没有其他影响
  • 输入完全由输入决定,任何内部、外部过程的状态改变不会影响 函数执行结果
  • reference transparency:引用透明,表达式可以用其结果 取代而不改变程序含义

语言基础

错误类型

  • trapped errors:导致程序终止执行错误
    • 除0
    • Java中数组越界访问
  • untrapped errors:出错后程序继续执行,但行为不可预知, 可能出现任何行为
    • C缓冲区溢出、Jump到错误地址

程序行为

  • forbidden behaviours:语言设计时定义的一组行为,必须 包括untrapped errorstrapped errors可选
  • undefined behaviours:未定义为行为,C++标准没有做出 明确规定,由编译器自行决定
  • well behaved:程序执行不可能出现forbidden behaviors
  • ill behaved:否则

语言类型

language_types

  • strongly typed:强类型,偏向于不能容忍隐式类型转换
  • weakly typed:弱类型,偏向于容忍隐式类型转换
  • statically typed:静态类型,编译时就知道每个变量类型, 因为类型错误而不能做的事情是语法错误
  • dynamically typed:动态类型,编译时不知道每个变量类型 ,因为类型错误而不能做的事情是运行时错误
  • 静态类型语言不定需要声明变量类型

    • explicitly typed:显式静态类型,类型是语言语法的 一部分,如:C
    • implicitly typed:隐式静态类型,类型由编译时推导 ,如:ML、OCaml、Haskell
  • 类型绑定

    • 强类型倾向于值类型,即类型和值绑定
    • 弱类型倾向于变量类型,类型和变量绑定,因而偏向于 容忍隐式类型转换

polymorphism

多态:能将相同代码应用到多种数据类型上方式

  • 相同对象收到不同消息、不同对象收到相同消息产生不同动作

Ad hoc Polymorphism

ad hoc polymorphism:接口多态,为类型定义公用接口

  • 函数重载:函数可以接受多种不同类型参数,根据参数类型有 不同的行为
  • ad hoc:for this, 表示专为某特定问题、任务设计的解决 方案,不考虑泛用、适配其他问题

Parametric Polymorphism

parametric polymorphism:参数化多态,使用抽象符号代替具体 类型名

  • 定义数据类型范型、函数范型

  • 参数化多态能够让语言具有更强表达能力的同时,保证类型安全

    • C++:函数、类模板
    • Rust:trait bound
  • 在函数式语言中广泛使用,被简称为polymorphism

Subtyping

subtyping/inclsion polymorphism:子类多态,使用基类实例 表示派生类

  • 子类多态可以用于限制多态适用范围

  • 子类多态一般是动态解析的,即函数地址绑定时间

    • 非多态:编译期间绑定
    • 多态:运行时绑定
    • C++:父类指针
    • Rust:trait bound

变量设计

LvalueRvalue

  • lvaluelocation value,可寻址
  • rvaluereadable value,可读取
  • 左值:引用内存中能够存储数据的内存单元的表达式

    • 使用表达式在内存中位置
    • 考虑其作为对象的身份
  • 右值:非左值表达式

    • 使用表达式的值
    • 考虑其作为对象的内容
  • 左值、右值最初源自C
    • 左值:可以位于赋值运算符=左侧的表达式
    • 右值:不可以位于赋值运算赋=左侧的表达式

左值

  • 任何左值都存储在内存中,所以都有一个地址
  • 左值声明后,地址不会改变,地址中存储的内容可能发生 改变
  • 左值的地址是一个指针值,可以被存储在内存中的、像数据 一样被修改

特点

  • 重要原则

    • 多数情况下,需要右值处可使用左值替代
    • 需要左值处不能用右值替代
  • 重要特点

    • 左值存在在变量中,有持久的状态
    • 右值常为字面常量、表达式求职过程中创建的临时对象, 没有持久状态

一等对象

一等对象:满足以下条件的程序实体

  • 在运行时创建
  • 能赋值给变量、数据结构中的元素
  • 能作为参数传递给函数
  • 能作为函数返回结果

高阶函数

高阶函数:以其他函数作为参数、返回函数作为结果的函数

短路求值

短路求值:布尔运算and/or中若结果已经确定,则不继续计算之后 表达式

  • x and y:首先对x求值

    • x为假停止计算
    • 否则继续对y求值再判断
  • x or y:首先对x求值

    • x为真则停止计算
    • 否则继续对y求值再判断
  • 返回值取决于语言实现
    • 确定返回布尔值:C/C++
    • 返回x、或y的求值结果:python

Hive

Hive简介

Hive是Hadoop平台上的数据仓库,面向结构化数据分析

  • 结构化数据文件映射为一张数据库表

  • 提供完整的SQL查询功能,所用语言称为HiveQL

    • Hive将HiveQL转换为MapReduce作业,在hadoop平台运行
    • Hive相当于一个在hadoop平台上的SQL Shell
    • 方便用户使用HiveQL快速实现简单数据分析、统计,而不必 开发专用MapReduce程序,学习成本低
  • 相较于传统关系数据库,Hive具有如下特点

    ||Hive|传统关系型数据库| |———|———|———-| |数据存储|HDFS分布式文件系统|服务器本地文件系统| |查询处理|MapReduce计算模型|自行设计的查询处理模型| |应用场景|海量数据分析处理|高性能查询,实时性好| |数据更新|不支持对具体数据行修改,只能覆盖、追加|支持| |事务处理|不支持|支持| |索引支持|不支持,一般需要对数据进行全部扫描|支持,多种索引| |扩展能力|基于Hadoop平台,存储、计算强大的扩展能力|扩展性较差| |数据加载|Writing Time Schema:数据加载时无需进行模式检查,在读取数据时对数据以一定模式进行解释|Reading Time Schema:要求数据必须符合数据库表结构|

Hive服务端组件

Driver

负责将用户的编写的HiveQL查询语句进行解析、编译、优化、生成 执行计划,然后调用底层MapReduce计算模型执行,包括

  • Compiler:编译器
  • Optimizer:优化器
  • Executor:执行器

MetaStore

元信息管理器,对Hive正确运行举足轻重

  • MetaStore实际上就是Thrift服务

    • MetaStore客户端(hive、spark shell等)和服务端通过 thrift协议进行通信
    • 客户端通过连接metastore服务,实现对元数据的存取
    • 通过Thrift获取元数据,屏蔽了访问MetaStore Database 所需的驱动、url、用户名、密码等细节
  • 负责存储元数据在关系型数据库(称为MetaStore Database)

    • 元数据包括Hive创建的database、table等元信息
    • 支持的关系型数据库
      • Derby:Apache旗下Java数据库
      • MySQL
  • MetaStore服务可以独立运行,可以让多个客户端同时连接、 甚至安装到远程服务器集群,保持Hive运行的健壮性

Embedded Metastore Server(Database Derby)

内嵌模式:使用内嵌的Derby数据库存储元数据

  • 不需要额外起Metastore服务
  • 一次只能一个客户端连接,使用做实验,不适合生产环境
  • Derby默认会在调用hive命令所在目录的metastore_db文件中 持久化元数据

embeded_metastore_database

Local Metastore Server

本地元存储

  • 采用外部数据库,支持

    • MySQL
    • Postgres
    • Orcale
    • MSSQL
  • 数据库独立于hive部署,hive服务使用JDBC访问元数据,多个 服务可以同时进行

  • 本地元存储不需要单独起metastore服务,用的是跟hive在同一 进程metastore服务

local_metastore_server

Remote Metastore Server

远程元存储

  • 类似于本地元存储,只是需要单独启动metastore服务,和hive 运行在不同的进程(甚至主机)中

  • 需要在每个客户端配置文件配置连接到该metastore服务

    • hive通过thrift访问metastore
  • 此模式可以控制到数据库的连接

remote_metastore_server

hiveserver2

基于的Thrift RPC实现

  • 远程客户端可以通过hiveserver2执行对hive的查询并返回结果

    • 支持多客户端并发、身份验证
  • 可以使用JDBC、ODBC、Thrift连接hiveserver2(Thrift Server 特性)

  • hiveserver2也能访问元数据,不依赖于metastore服务

Hive客户端组件

CLI

Command Line Interface

  • 允许用户交互式的使用Hive

THrift Client/beeline

基于Thrift的JDBC Client

  • 包括JDBC/ODBC驱动程序

WEB GUI

允许用户通过WEB GUI图形界面访问Hive

  • 需要首先启动Hive Web Interface服务

Hive查询处理

过程

  1. 用户提交HQL至Driver
  2. Driver把查询交给Compiler,Compiler使用MetaStore中元信息 检查、编译
  3. 查询经过Optimizer优化交由Executor Engine执行,转换为 MapReduce作业后调用MapReduce执行
  4. MapReduce存取HDFS,对数据进行处理,查询结果返回Driver

数据类型

  • 基础数据类型

    • Integer
    • Float
    • Double
    • String
  • 复杂数据类型:通过嵌套表达复杂类型

    • Map
    • List
    • Struct
  • 还允许用户自定以类型、函数扩展系统

数据存储模型

使用传统数据库:Table、Row、Column、Partition等概念,易于 理解

Database

相当于关系型数据库中的Namespace

  • 将不同用户数据隔离到不同的数据库、模式中

Table

表格

  • 逻辑上由存储的数据、描述数据格式的相关元数据组成

    • 表格数据存放在分布式文件系统(HDFS)中
    • 元数据存储在MetaStore服务指定关系型数据库中
  • 创建表格、加载数据之前,表格在HDFS中就是一个目录, 表格分为两种类型

    • 托管表:数据文件存放在Hive数据仓库中,即HDFS中的一个 目录,是Hive数据文件默认存放路径
    • 外部表:数据文件可以存放在其他文件系统中

Partition

根据“分区列”的值,对表格数据进行粗略划分的极值

  • 存储上:是Hive中表格主目录的子目录,名字即为定义的分区列 名字

  • 逻辑上:分区不是表中的实际字段,是虚拟列

    • 根据虚拟列(可能包含多个实际字段)划分、存储表格数据
    • 同一虚拟列中字段通常应该经常一起被查询,这样在需要 存取部分数据字段时,可以只扫描部分表

Bucket

Table、Partition都是目录级别的数据拆分,指定Bucket的表格, 数据文件将按照规律拆分成多个文件

  • 每个桶就是table、partition目录中的文件

  • 一般使用Hash函数实现数据分桶,创建表时,需要指定桶数量、 分桶操作依据的列

  • 用户执行Sample查询时,Hive可以使用分桶信息,有效的Prune Data,如:对每个目录下单个桶文件进行查询