MySQL窗口_分布、前后、头尾函数

MySQL窗口_分布、前后、头尾函数,第1张

接上一篇,这一篇主要介绍三类窗口函数,分布函数、前后函数和头尾函数。

【分布函数】

PERCENT_RANK基于RANK()函数的排序结果,percent_ranks列按照公式(rank-1) / (rows-1)带入rank值(row_num列)和rows值,其中,rank为RANK()函数产生的序号,rows为当前窗口的记录总行数。

CUME_DIST,分组内小于等于当前rank值的行数/分组内总行数,这个函数比percen_rank使用场景更多。可以用于计算大于等于或小于等于当前订单金额的订单比例有多少。

【前后函数】

分区中位于当前行前n行(LAG)或后n行(LEAD)的记录值。这两个函数在实际中还是有使用场景,比如要查询上一个订单距离当前订单的时间间隔,或者本条订单距离下一条订单的时间间隔。

如果要计算距离上一条订单的天数,只需要增加一列,用DATEDIFF函数把两个日期相减就可以了。如果是第一条订单,就会返回空值。

【头尾函数】

头尾函数FIRST_VAL和LAST_VAL函数,用来得到分区中的第一个或最后一个指定参数的值。可以用来查询每个用户第一次和最后一次的订单数据信息,然后就行比较 *** 作。需要注意的是,最后一条订单时间是基于当前订单时间来看的,所有是等于当前订单时间。

End

◆ PowerBI开场白

◆ Python高德地图可视化

◆ Python不规则条形图

参考: https://www.jianshu.com/p/5e0062f6cf62

图中是两组分片,红色我们称为shard1,蓝色我们称为shard2

51 52是服务器

两个3307互为主从(双主),3309是本地3307的从库

说明:没有明确说明是只在某一个节点上做的,就是两个节点都做

两台虚拟机 db01 db02

每台创建四个mysql实例:3307 3308 3309 3310

mysql软件我们之前已完成二进制安装,直接初始化即可

我们server-id规划为:db01上是7/8/9/10,db02上是17/18/19/20

"箭头指向谁是主库"

10.0.0.51:3307<-----> 10.0.0.52:3307

10.0.0.51:3309------> 10.0.0.51:3307

10.0.0.52:3309------> 10.0.0.52:3307

两个分片,每个分片四个mysql节点

shard1:

Master:10.0.0.51:3307

slave1:10.0.0.51:3309

Standby Master:10.0.0.52:3307

slave2:10.0.0.52:3309

shard2:

Master:10.0.0.52:3308

slave1:10.0.0.52:3310

Standby Master:10.0.0.51:3308

slave2:10.0.0.51:3310

shard1

10.0.0.51:3307 <----->10.0.0.52:3307

db02

db01

db02

10.0.0.51:3309 ------>10.0.0.51:3307

db01

10.0.0.52:3309 ------>10.0.0.52:3307

db02

shard2

10.0.0.52:3308 <----->10.0.0.51:3308

db01

db02

db01

10.0.0.52:3310 ----->10.0.0.52:3308

db02

10.0.0.51:3310 ----->10.0.0.51:3308

db01

这个复制用户在谁上建都行

注:如果中间出现错误,在每个节点进行执行以下命令

常见方案:

360 Atlas-Sharding 360

Alibaba cobar 阿里

Mycat 开源

TDDL 淘宝

Heisenberg 百度

Oceanus 58同城

Vitess 谷歌

OneProxy

DRDS 阿里云

我们装的是openjdk,不是官方的那个

Mycat-server-xxxxx.linux.tar.gz

http://dl.mycat.io/

配置环境变量

我们mycat的命令也是在bin目录下

启动

8066就是对外提供服务的端口,9066是管理端口

连接mycat:

默认123456

db01:

我们一般先把原schema.xml备份,然后自己新写一个:

xml和html看起来差不多,xml是从下往上调用的

前三行我们不用看,直接从第四行schema开始看起:

定义了schema,然后以/schema结尾

为什么要用逻辑库?

业务透明化

此配置文件就是实现读写分离的配置

重启mycat

读写分离测试

总结:

以上案例实现了1主1从的读写分离功能,写 *** 作落到主库,读 *** 作落到从库.如果主库宕机,从库不能在继续提供服务了。

我们推荐这种架构

一写三读,

不设置双写的原因是:性能没提升多少,反而引起主键冲突的情况

配置文件:

之后重启:mycat restart

真正的 writehost:负责写 *** 作的writehost

standby writeHost :和readhost一样,只提供读服务

我们此处写了两个writehost,默认使用第一个

当写节点宕机后,后面跟的readhost也不提供服务,这时候standby的writehost就提供写服务,

后面跟的readhost提供读服务

测试:

读写分离测试

对db01 3307节点进行关闭和启动,测试读写 *** 作

结果应为另一台(52)的3307(17)是写,3309(19)是读

一旦7号节点恢复,此时因为7落后了,写节点仍是17

balance属性

负载均衡类型,目前的取值有3种:

writeType属性

负载均衡类型,目前的取值有2种:

switchType属性

-1 表示不自动切换

1 默认值,自动切换

2 基于MySQL主从同步的状态决定是否切换 ,心跳语句为 show slave status

datahost其他配置

<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1">

maxCon="1000":最大的并发连接数

minCon="10" :mycat在启动之后,会在后端节点上自动开启的连接线程,长连接,好处是连接速度快,弊端是占内存

tempReadHostAvailable="1"

这个一主一从时(1个writehost,1个readhost时),可以开启这个参数,如果2个writehost,2个readhost时

<heartbeat>select user()</heartbeat> 监测心跳

其他参数sqlMaxLimit自动分页,必须在启用分表的情况下才生效

创建测试库和表:

我们重启mycat后连接到8066

发现跟一个库一样,实际上已经分到不同的物理硬件上了

分片:对一个"bigtable",比如说t3表

热点数据表 核心表

(1)行数非常多,800w下坡

(2)访问非常频繁

分片的目的:

(1)将大数据量进行分布存储

(2)提供均衡的访问路由

分片策略:

范围 range 800w 1-400w 400w01-800w 不适用于业务访问不均匀的情况

取模 mod(取余数) 和节点的数量进行取模

枚举 按枚举的种类分,如移动项目按省份分

哈希 hash

时间 流水

优化关联查询(否则join的表在不同分片上,效率会比单库还要低)

全局表

ER分片

案例:移动统一:先拆出边缘业务,再按地域分片,但对应用来说是统一的

vim rule.xml

<tableRule name="auto-sharding-long">

<rule>

<columns>id</columns>

<algorithm>rang-long</algorithm>

</rule>

<function name="rang-long"

class="io.mycat.route.function.AutoPartitionByLong">

<property name="mapFile">autopartition-long.txt</property>

</function>

===================================

vim autopartition-long.txt

0-10=0

11-20=1

创建测试表:

mysql -S /data/3307/mysql.sock -e "use taobaocreate table t3 (id int not null primary key auto_increment,name varchar(20) not null)"

mysql -S /data/3308/mysql.sock -e "use taobaocreate table t3 (id int not null primary key auto_increment,name varchar(20) not null)"

测试:

重启mycat

mycat restart

mysql -uroot -p123456 -h 127.0.0.1 -P 8066

insert into t3(id,name) values(1,'a')

insert into t3(id,name) values(2,'b')

insert into t3(id,name) values(3,'c')

insert into t3(id,name) values(4,'d')

insert into t3(id,name) values(11,'aa')

insert into t3(id,name) values(12,'bb')

insert into t3(id,name) values(13,'cc')

insert into t3(id,name) values(14,'dd')

取余分片方式:分片键(一个列)与节点数量进行取余,得到余数,将数据写入对应节点

vim schema.xml

<table name="t4" dataNode="sh1,sh2" rule="mod-long" />

vim rule.xml

<property name="count">2</property>

准备测试环境

创建测试表:

mysql -S /data/3307/mysql.sock -e "use taobaocreate table t4 (id int not null primary key auto_increment,name varchar(20) not null)"

mysql -S /data/3308/mysql.sock -e "use taobaocreate table t4 (id int not null primary key auto_increment,name varchar(20) not null)"

重启mycat

mycat restart

测试:

mysql -uroot -p123456 -h10.0.0.52 -P8066

use TESTDB

insert into t4(id,name) values(1,'a')

insert into t4(id,name) values(2,'b')

insert into t4(id,name) values(3,'c')

insert into t4(id,name) values(4,'d')

分别登录后端节点查询数据

mysql -S /data/3307/mysql.sock

use taobao

select * from t4

mysql -S /data/3308/mysql.sock

use taobao

select * from t4

t5 表

id name telnum

1 bj 1212

2 sh 22222

3 bj 3333

4 sh 44444

5 bj 5555

sharding-by-intfile

vim schema.xml

<table name="t5" dataNode="sh1,sh2" rule="sharding-by-intfile" />

vim rule.xml

<tableRule name="sharding-by-intfile">

<rule><columns>name</columns>

<algorithm>hash-int</algorithm>

</rule>

</tableRule>

<function name="hash-int" class="org.opencloudb.route.function.PartitionByFileMap">

<property name="mapFile">partition-hash-int.txt</property>

<property name="type">1</property>

<property name="defaultNode">0</property>

</function>

partition-hash-int.txt 配置:

bj=0

sh=1

DEFAULT_NODE=1

columns 标识将要分片的表字段,algorithm 分片函数, 其中分片函数配置中,mapFile标识配置文件名称

准备测试环境

mysql -S /data/3307/mysql.sock -e "use taobaocreate table t5 (id int not null primary key auto_increment,name varchar(20) not null)"

mysql -S /data/3308/mysql.sock -e "use taobaocreate table t5 (id int not null primary key auto_increment,name varchar(20) not null)"

重启mycat

mycat restart

mysql -uroot -p123456 -h10.0.0.51 -P8066

use TESTDB

insert into t5(id,name) values(1,'bj')

insert into t5(id,name) values(2,'sh')

insert into t5(id,name) values(3,'bj')

insert into t5(id,name) values(4,'sh')

insert into t5(id,name) values(5,'tj')

a b c d

join

t

select t1.name ,t.x from t1

join t

select t2.name ,t.x from t2

join t

select t3.name ,t.x from t3

join t

使用场景:

如果你的业务中有些数据类似于数据字典,比如配置文件的配置,

常用业务的配置或者数据量不大很少变动的表,这些表往往不是特别大,

而且大部分的业务场景都会用到,那么这种表适合于Mycat全局表,无须对数据进行切分,

要在所有的分片上保存一份数据即可,Mycat 在Join *** 作中,业务表与全局表进行Join聚合会优先选择相同分片内的全局表join,

避免跨库Join,在进行数据插入 *** 作时,mycat将把数据分发到全局表对应的所有分片执行,在进行数据读取时候将会随机获取一个节点读取数据。

vim schema.xml

<table name="t_area" primaryKey="id" type="global" dataNode="sh1,sh2" />

后端数据准备

mysql -S /data/3307/mysql.sock

use taobao

create table t_area (id int not null primary key auto_increment,name varchar(20) not null)

mysql -S /data/3308/mysql.sock

use taobao

create table t_area (id int not null primary key auto_increment,name varchar(20) not null)

重启mycat

mycat restart

测试:

mysql -uroot -p123456 -h10.0.0.52 -P8066

use TESTDB

insert into t_area(id,name) values(1,'a')

insert into t_area(id,name) values(2,'b')

insert into t_area(id,name) values(3,'c')

insert into t_area(id,name) values(4,'d')

A

join

B

为了防止跨分片join,可以使用E-R模式

A join B

on a.xx=b.yy

join C

on A.id=C.id

<table name="A" dataNode="sh1,sh2" rule="mod-long">

<childTable name="B" joinKey="yy" parentKey="xx" />

</table>

分区介绍:

一、什么是分区?

所谓分区,就是将一个表分成多个区块进行 *** 作和保存,从而降低每次 *** 作的数据,提高性能。而对于应用来说则是透明的,从逻辑上看只有一张表,但在物理上这个表可能是由多个物理分区组成的,每个分区都是独立的对象,可以进行独立处理。

二、分区作用

1.可以逻辑数据分割,分割数据能够有多个不同的物理文件路径。

2.可以存储更多的数据,突破系统单个文件最大限制。

3.提升性能,提高每个分区的读写速度,提高分区范围查询的速度。

4.可以通过删除相关分区来快速删除数据

5.通过跨多个磁盘来分散数据查询,从而提高磁盘I/O的性能。

6.涉及到例如SUM()、COUNT()这样聚合函数的查询,可以很容易的进行并行处理。

7.可以备份和恢复独立的分区,这对大数据量很有好处。

三、分区能支持的引擎

MySQL支持大部分引擎创建分区,入MyISAM、InnoDB等;不支持MERGE和CSV等来创建分区。同一个分区表中的所有分区必须是同一个存储引擎。值得注意的是,在MySQL8版本中,MyISAM表引擎不支持分区。

四、确认MySQL支持分区

从MySQL5.1开始引入分区功能,可以如下方式查看是否支持:

老版本用:SHOW VARIABLES LIKE '%partition%'

新版本用:show plugins

五、分区类型

1. RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。

例如,可以将一个表通过年份划分成两个分区,2001 -2010年、2011-2020。

2. LIST分区:类似于RANGE分区,LIST是列值匹配一个离散值集合中的某个值来进行选择。

比如 根据字段 把值为1、3、5的放到一起,2、4、6的另外放到一起 等等...

3. HASH分区:基于用户定义的表达式的返回值来进行选择分区,该表达式使用将要插入到表中的这些行的列值来进行计算,这个函数必须产生非负整数值。

通过HASH运算来进行分区,分布的比较均匀

4. KEY分区:类似于按HASH分区,由MySQL服务器提供其自身的哈希函数。

按照KEY进行分区类似于按照HASH分区

六、使用分区注意事项

1. 如果表中存在primary key 或者 unique key 时,分区的列必须是paimary key或者unique key的一个组成部分,也就是说,分区函数的列只能从pk或者uk这些key中取子集

2. 如果表中不存在任何的paimary key或者unique key,则可以指定任何一个列作为分区列

3. 5.5版本前的RANGE、LIST、HASH分区要求分区键必须是int;MySQL5.5及以上,支持非整形的RANGE和LIST分区,即:range columns 和 list columns (可以用字符串来进行分区)。

七、分区命名

1. 分区的名字基本上遵循其他MySQL 标识符应当遵循的原则,例如用于表和数据库名字的标识符。应当注意的是,分区的名字是不区分大小写的。

2. 无论使用何种类型的分区,分区总是在创建时就自动的顺序编号,且从0开始记录。

八、 创建分区

1. RANGE分区:

解读:以上为 uuid小于5时放到p0分区下,uuid大于5且小于10放到p1分区下,uuid大于10且小于15放到p2分区下,uuid大于15 一直到最大值的存在p3分区下

2. LIST分区:

解读:以上为uuid 等于1/2/3/5时放到p0分区,7/9/10放到p1分区,11/15放到p2分区。当时用insert into时 如果uuid的值不存在p0/p1/p2分区时,则会插入失败而报错。

3. HASH分区:

HASH分区主要用来确保数据在预先确定数目的分区中平均分布。在RANGE分区和LIST分区中必须明确指定一个指定的列值或列值集合以指定应该保存在哪个分区中。而在HASH分区中,MySQL会自动完成这些工作,要做的只是基于将要被哈希的列值指定一个表达式,以及指定被分区的表将要被分割成的分区数量,如:

解读:MySQL自动创建3个分区,在执行insert into时,根据插入的uuid通过算法来自动分配区间。

注意:

(1) 由于每次插入、更新、删除一行,这个表达式都要计算一次,这意味着非常复杂的表达式可能会引起性能问题,尤其是在执行同时影响大量行的运算(例如批量插入)的时候。

(2) 最有效率的哈希函数是只对单个表列进行计算,并且它的值随列值进行一致的增大或减小,因为这考虑了在分区范围上的“修剪”。也就是说,表达式值和它所基于的列的值变化越接近,就越能有效地使用该表达式来进行HASH分区。

3.1:线性HASH分区

线性HASH分区在“PARTITION BY”子句中添加“LINEAR”关键字。

线性HASH分区的有点在于增加、删除、合并和拆分分区将变得更加快捷,有利于处理含有及其大量数据的表。它的缺点在于各个分区间数据的分布不大可能均衡。

4. KEY分区

类似于HASH分区,HASH分区允许用户自定义的表达式,而KEY分区则不允许使用用户自定义的表达式;HASH分区只支持整数分区,KEY分区支持除了blob和text类型之外的其他数据类型分区。

与HASH分区不同,创建KEY分区表的时候,可以不指定分区键,默认会选择使用主键或唯一键作为分区键,没有主键或唯一键,就必须指定分区键。

解读:根据分区键来进行分区

5. 子分区

子分区是分区表中,每个分区的再次分割,适合保存非常大量的数据。

解读:主分区使用RANGE按照年来进行分区,有3个RANGE分区。这3个分区中又被进一步分成了2个子分区,实际上,整个表被分成了3 * 2 = 6个分区。每个子分区按照天进行HASH分区。小于2017的放在一起,2017-2020的放在一起,大于2020的放在一起。

注意:

(1) 在MySQL5.1中,对于已经通过RANGE或LIST分区了的表在进行子分区是可能的。子分区既可以使用HASH分区,也可以使用KEY分区。这也被称为复合分区。

(2) 每个分区必须有相同数量的子分区。

(3) 如果在一个分区表上的任何分区上使用SUBPARTITION来明确定义任何子分区,那么就必须定义所有的子分区。

(4) 每个SUBPARTITION子句必须包含(至少)子分区的一个名字。

(5) 在每个子分区内,子分区的名字必须是惟一的,目前在整个表中,也要保持唯一。例如:

子分区可以用于特别大的表,可以在多个磁盘间分配数据和索引。例如:

九、MySQL分区处理NULL值的方式

十、分区管理概述

可以对分区进行添加、删除、重新定义、合并或拆分等管理 *** 作。

① RANGE和LIST分区的管理

1. 删除分区语句如:alter table tbl_test drop partition p0

注意:

(1) 当删除了一个分区,也同时删除了该分区中所有的数据。

(2) 可以通过show create table tbl_test来查看新的创建表的语句。

(3) 如果是LIST分区的话,删除的数据不能新增进来,因为这些行的列值包含在已经删除了的分区的值列表中。

2. 添加分区语句如:alter table tbl_test add partition(partition p3 values less than(50))

注意:

(1) 对于RANGE分区的表,只可以添加新的分区到分区列表的最高端。

(2) 对于LIST分区的表,不能添加已经包含在现有分区值列表中的任意值。

3. 如果希望能不丢失数据的条件下重新定义分区,可以使用如下语句:

REORGANIZE会对分区的数据进行重构。

ALTER TABLE tbl_name REORGANIZE PARTITION partition_list INTO(partition_definitions)

(1) 拆分分区如:

ALTER TABLE tbl_name REORGANIZE PARTITION partition_list INTO(partition s0 values less than(5),partition s1 values less than(10))

或者如:

ALTER TABLE tbl_name REORGANIZE PARTITION p0 INTO(partition s0 values in(1,2,3), partition s1 values in(4,5))

(2) 合并分区如:ALTER TABLE tbl_name REORGANIZE PARTITION s0,s1 INTO(partition p0 values in(1,2,3,4,5))

4. 删除所有分区,但保留数据,形式:ALTER TABLE tbl_name remove partitioning

② HASH和KEY分区的管理

1. 减少分区数量语句如:ALTER TABLE tbl_name COALESCE PARTITION 2

2. 添加分区数量语句如:ALTER TABLE tbl_name add PARTITION partitions 2

③ 其他分区管理语句

1. 重建分区:类似于先删除保存在分区中的所有记录,然后重新插入它们,可用于整理分区碎片。如:ALTER table tbl_name REBUILD PARTITION p2,p3

2. 优化分区:如果从分区中删除了大量的行,或者对一个带有可变长度的行(也就是说,有VARCHAR,BLOB或TEXT类型的列)做了许多修改,可以使用 ALTER TABLE tbl_name OPTIMIZE PARTITION来收回没有使用的空间,并整理分区数据文件的碎片。如:ALTER TABLE tbl_name OPTIMIZE PARTITION p2,p3

3. 分析分区:读取并保存分区的键分布,如:ALTER TABLE tbl_name ANALYZE PARTITION p2,p3

4. 检查分区:检查分区中的数据或索引是否已经被破坏,如:ALTER TABLE tbl_name CHECK PARTITION p2,p3

5. 修补分区:修补被破坏的分区,如:ALTER TABLE tbl_name REPAIR PARTITION p2,p3

十、查看分区信息

1. 查看分区信息:select * from information_schema.partitions where table_schema='arch1' and table_name = 'tbl_test' G

2. 查看分区上的数据:select * from tbl_test partition(p0)

3. 查看MySQL会 *** 作的分区:explain partitions select * from tbl_test where uuid = 2

十一、 局限性

1. 最大分区数目不能超过1024,一般建议对单表的分区数不要超过50个。

2. 如果含有唯一索引或者主键,则分区列必须包含在所有的唯一索引或者主键在内。

3. 不支持外键。

4. 不支持全文索引,对分区表的分区键创建索引,那么这个索引也将被分区。

5. 按日期进行分区很合适,因为很多日期函数可以用。但是对字符串来说合适的分区函数不太多。

6. 只有RANGE和LIST分区能进行子分区,HASH和KEY分区不能进行子分区。

7. 临时表不能被分区。

8. 分区表对于单条记录的查询没有优势。

9. 要注意选择分区的成本,没插入一行数据都需要按照表达式筛选插入的分区。

10. 分区字段尽量不要可以为null


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/7463829.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-06
下一篇 2023-04-06

发表评论

登录后才能评论

评论列表(0条)

保存