分布式数据库从过去成为NoSQL的数据库发展开始,底层的数据存储结构变得多样化,包括KV、文档、列式等结构。各自有本身擅长的业务应用场景,例如操做型和分析型就是最简单的区分。shell
然而SQL的支持成为了业界的共识。 SQL语言几十年的发展已经很是成熟,技术基础也很是普遍。全世界90%以上的开发,不管业务操做型仍是分析型都以SQL的数据处理为主。不管底层数据存储结构是关系型仍是非关系型都将对系统开发透明。开发者只需根据本身的业务场景来选择合适的数据库,但不须要改变自身的开发模式。数据库
本篇文章主要是向你们介绍分布式数据库的关联查询基本原理,以及用户在使用SequoiaSQL作关联查询时应该注意哪些地方,也但愿用户可以经过本篇文章了解到更多分布式数据库操做的相关知识,同时帮助用户快速掌握SequoiaSQL的开发和使用技巧。缓存
在关系型数据库中若是要介绍关联查询,那么必然会涉及到数据库范式设计的内容。那么为何关系型数据库会有范式设计这种开发理念,这还得从关系型数据库的发展历程提及。服务器
关系型数据库是从上世纪70年代开始发展起来的,那个时候硬件设备的成本价格是很是高的,那个时候像十几MB的存储硬件就已是顶配级别了,即便到了90年代,硬盘的存储空间也就是达到几百兆级别,价格依然昂贵。架构
因此关系型数据库是在一个存储资源极度紧张的背景下诞生的,在这种状况下,数据库研发的理念理所固然的往“尽量利用存储空间”方向发展,一样使用数据库的用户也一样想尽办法往数据库中多存储有价值数据库。分布式
资深的DBA明白,要想数据存储冗余低,那么遵循范式设计是很是有效的方法。工具
范式设计,核心思想就是尽量确保表中每一列的数据都不会产冗余,例如第一范式里要求数据库表中全部字段值都是不可分解的原子值,第二范式里要求数据库表中的每列都和主键相关,第三范式里要求数据库表中消除与主键之间的间接相关。oop
因为关系型数据库的范式设计开发理念,因此会致使过去建设一个完整的系统,会有比较复杂的数据模型,可能一个系统会包含几十甚至上百张数据表,而每张表之间都有主外建关联关系。性能
在这种数据模型下,用户若是要在系统中查询某些数据,则可能须要同时用到几张表甚至是几十张表的数据才可以获得完整的结果集。因此要在这种遵循范式设计的系统中操做数据表,就难以免须要用到数据库的关联方法。学习
在传统的关系型数据库中,最多见的关联策略有三种,分别是:NL Join(Nest Loop Join)、Hash Join和Merge Join。
NL Join的技术原理相对来讲比较好理解,实际上读者能够理解为两张表一条记录一条记录地做比对,若是符合关联条件则关联成功。
使用伪代码来表示则是
for (int i=0; i<t1.length; ++i) { for (int j=0; j<t2.length; ++j) { if ( t1[i] == t2[j] ) { return ( t1[i], t2[j] ) } } }
在没有索引状况作NL Jion,复杂度为O(N*M)。
NL Join关联方法一般使用在
1) 左表(也叫驱动表、外部表)数据量较小
2) 右表(也叫探查表、内部表)中匹配字段支持索引查询,而且可以作高效查询
典型的SQL命令以下
for (int i=0; i<t1.length; ++i) { for (int j=0; j<t2.length; ++j) { if ( t1[i] == t2[j] ) { return ( t1[i], t2[j] ) } } }
Hash Join的技术原理是将其中一张记录较少的数据表加载到Hash Table上,再经过遍历另一张表的数据,经过对关联字段作Hash后对Hash Table上的数据作关联匹配,若是匹配成功,则证实该记录符合关联条件,不然继续读取下一条记录作关联。
该方法主要利用Hash Table的分区以及内存提高匹配速度,用户须要确保服务器的内容足以缓存下数据量较少的表的全部数据,不然超出部分将须要写入到磁盘的临时文件上。所以用户能够在内存不足状况下,考虑采用SSD存储来提高临时文件的读写性能。
在内存足够的状况下,Hash Join 的复杂度仅仅为O(N+M)
因此Hash Join主要使用的场景是
1) 关联的表数据量较大
2) 机器内存足以缓存所有或者绝大部分关联数据
3) 只能用在等值匹配关联匹配上
典型的SQL命令以下
select t1.name,t2.info from t1,t2 where t1.id=t2.id;
Merge Join也被称为Sort Merge Join,顾名思义,就是要对须要关联的表根据关联字段作排序后再作匹配关联计算。
Merger Join的实现步骤比较复杂,读者能够理解为程序同时对两张已经排好序的表从头开始读取匹配字段的值,若是二者值不相同,则一方选择下一个值继续匹配,若是匹配成功,则一方读取下一个值继续匹配,直至任意一张表的全部数据读取完毕,匹配程序结束。
例如SQL引擎要对t1和t2两张表作Merge Join,两表的排序方式为升序排序,Merge Join的过程以下图示。
SQL引擎从两表的第一行开始匹配,发现左表的1值小于右表的2值,因此左表读取下一条记录继续匹配,当左右两表的值都为2时,该记录符合匹配条件,而后右表读取下一条记录继续匹配,发现二者不等于而且左表值小于右表值后,左表读取下一条继续匹配,一直到t1或者t2表的数据所有读区完毕,Merge Join才算结束。
Merge Join若是不考虑排序的开销,效率要比Hash Join要高,可是若是左右表都须要作复杂度O(n*)的排序,则关联效率确定要比Hash Join要低。
Merge Join主要使用的场景为
1) 关联的字段在两张表中都索引,能够支持快速排序,或者须要关联的表的关联字段自己是有序的
2) 两张数据量较大的表关联,Merge Join的性能会比 NL Join性能要好
典型的SQL命令以下
select t1.name,t2.info from t1,t2 where t1.id=t2.id order by t1.id , t2.id;
SequoiaSQL是SequoiaDB的SQL引擎,为用户提供基于SQL语言访问SequoiaDB的方法,可以大大下降用户须要从新学习SequoiaDB驱动API的难度,继续沿用JDBC驱动开发应用程序,同时也能利用成熟的GUI工具操做数据库。
SequoiaDB自己是一款分布式文档型数据库,它为用户提供了各类开发语言的驱动程序,例如:Java、PHP、Python、C#、C++、C、Javascript等,可是这些驱动程序都只支持使用API方式操做数据库。
可是用户若是但愿使用SQL语言对SequoiaDB作开发,也能够选择部署SequoiaSQL或者PostgreSQL来补充SequoiaDB的开发接口,这样用户就可使用标准的JDBC驱动开发程序代码了。
目前用户能够经过SequoiaSQL或者PostgreSQL来扩展SequoiaDB的开发接口,而且二者都支持2003 SQL标准。可是二者在底层的运行机制上仍是有所区别,最明显一点就是Sequoia SQL支持NL Join和Hash Join两种关联策略,而以PostgreSQL作为SequoiaDB的SQL引擎只可以支持Hash Join一种关联策略。
因为SequoiaSQL在作关联查询时,实际上数据的提供者就是SequoiaDB,因此在不一样的关联策略生效时,对于SequoiaDB数据库有不一样的表现。
例如
1) 若是SequoiaSQL使用Hash Join策略执行关联查询,则SequoiaDB会表现出大量的数据读,而索引读则为零;
2) 若是Sequoia SQL使用NL Join策略执行关联查询,则SequoiaDB会有较大的索引读,而数据读和索引读的数值至关。
用户能够在sdb shell中执行如下快照命令查看
db.snapshot(SDB_SNAP_DATABASE)
快照结果中,TotalDataRead表明数据读的数值,TotalIndexRead表明索引读的数据,该数值始终保持递增状态,若是用户想用更加简单的方法了解当前数据库平均每秒数据读和索引读的数值,可使用sdbtop工具进行查看。
SequoiaSQL的NL Join功能由引擎配置文件的enable_nestloop参数控制是否开启,固然该功能默认是开启的。
SequoiaSQL在作关联查询时须要执行NL Join关联策略,须要知足如下条件
1) enable_nestloop参数设置为on
2) 关联右表(也叫探查表、内部表)的关联字段有建立索引
3) 关联左表(也叫驱动表、外部表)的数据量相对较少
SequoiaSQL在执行关联查询时,若是不知足NL Join的要求,则自动选择使用Hash Join完成关联查询。
用户在SequoiaSQL的操做控制窗口中,能够经过explain+SQL命令查看引擎的关联策略,例如存在duebill和contract 两张表,每张表中都存储了2000万记录,而且两表的关联条件为
duebill.relativeserialno2=contract.serialno
若是开始时只对duebill表中relativeserialno2 建立了索引,而contract表中 serialno 字段没有索引,此时使用expalin查看访问计划,用户将会看到引擎是使用Hash join完成关联查询。
此时使用Hash join的SQL查询效率较低,须要18.9秒
而若是用户对contract表中的serialno 字段建立索引后,再使用相同的SQL查看引擎的访问计划,将会变成NL join策略。
并且用户能够发现使用NL join 的查询效率比使用Hash join的查询效率高不少,关联查询只须要7毫秒。
本篇文章主要向读者介绍了数据库在作关联查询时,数据库底层的技术原理。做者结合SequoiaSQL自身的技术特性,向用户介绍在什么场景下应该使用哪一种关联策略,以及若是用户须要使用NL Join关联策略,SequoiaDB数据库应该知足什么条件才可以正确触发SequoiaSQL的NL Join关联查询。
SequoiaDB是一款分布式文档型数据库,自从在2013年发布以后,受到愈来愈开发者的喜好和普遍的使用。SequoiaDB通过这些年的发展,功能覆盖已经较为全面,例如支持分布式事务、完整对接大数据主流产品、异地灾备、分布式块存储等,而且SequoiaDB还为开发者提供完整的SQL支持。
目前,SequoiaDB自研的SQL访问组件SequoiaSQL做为企业版的功能之一已经提供给上百家企业用户使用,而且已经实现分布式架构下的SQL 2003支持。
对于SequoiaDB社区版用户,咱们能够经过SequoiaDB对接PostgreSQL 实现社区版的分布式SQL访问。这一应用方式基本也能够知足大部分的社区版需求。