瞿璐祎的博客

try something new


  • Home

  • Tags

  • Categories

  • Archives

  • Schedule

What’s Really New with NewSQL

Posted on 2020-08-27 | In Paper


先导

为什么需要NewSQL?

  • 数据的急速扩增,需要数据库具有很强的扩展性,往往有两种扩展方式:
    • 垂直扩展:scale-up
    • 水平扩展: scale-out,采用中间件,做sharding的方式,即分库分表的方式

NoSQL

代表性的DB

  • Google’s BigTable — HBASE(开源版)
  • Amazon’s Dynamo — Cassandra(开源版)
  • MongoDB
  • Redis(键值型数据库)

特性

  • 不保证强一致性(故不适用金融服务),需要在应用逻辑里处理最终一致性的问题
  • 不支持事务
  • 数据模型:键值对、图形、文档

NewSQL

特性

  • 可扩展性
  • 针对读写事务需要满足:
    • 执行时间短
    • 一般只查询一小部分数据,通过使用索引来达到高效查询的目的,即避免全表扫描或者大规模的分布式join
    • 一般执行相同的命令,使用不同的输入参数

数据库的历史

early 1970s

  • IBM’s SystemR
  • the University of California’s INGRES
  • Oracle(和系统R的设计很像)
  • DB2 1983

late 1980s and early 1990s

  • 出现面向对象的数据库(但夭折了),不过他的思想延续了,如加入对象和XML
  • MYSQL 1995
  • PostgreSQL 1994

2000s

  • 2000s,随着互联网的应用越来越多,对数据库的要求也高起立了,针对这个,有一部分人提出将数据库scale-up,一直更新数据库的硬件资源,不断升级。
  • 另一部分提出了使用一个定制的中间件,在一组便宜的机器上构建单节点的DBMS,主要是中间件的功劳!!(感觉这个接近现在newsql的概念),中间件需要做的事情可多了,对应用端不偏于访问数据库的queries进行重写,之后再发给底下的机器上,让它们执行完返回,之后中间件再结合它们的合并他们的返回结果给应用端。能力大了,担子也就自然大了,因此导致中间件这个节点负载过大,产生性能瓶颈(这是我自己的想法)
    • 中间件的典型:
      • Google’s MySQL-based cluster(这方法被Facebook采取,至今仍在使用)
      • eBay’s Oracle-based cluster(join贼不方便。ebay要求开发人员在应用层自己去实现Join)
  • 最终,提出分布式DBMSs,因为传统数据库关注一致性和正确性的同时,忽视了可用性和性能,但这种trade-off对于如今的互联网应用来说却是不合适的。而且使用full-featured DBMS(像MySQL)开销很大(限制太多)

mid to late 2000s

  • NoSQL出现了,他们放弃了强事务保证和传统数据库中的关系模型,选择了最终一致性和可选择的数据模型(key/value,graphs,documents)
  • 代表:
    • Google’s BigTable(未开源)
    • Amazon’s Dynamo(未开源)
    • Facebook’s Cassandra(基于BigTable & Dynamo)
    • PowerSet’s Hbase(基于BigTable)
    • MongoDB
  • NoSQL的好处是开发人员会更关注他们的应用场景而并非如何去扩展数据库
  • 但一些机构(如Google)发现NoSQL会导致他们的开发人员耗费太长时间去处理数据一致性和事务。这些机构职能要么去scale-up机器,要么使用他们自己的定制化的中间层去支持事务。

NEWSQL

  • 既想拥有NoSQL一样的可扩展性,又想保持传统数据库中的关系模型和事务支持
  • NewSQL DBMSs 读写事务的特点:
    • short-lived
    • 只用到少部分的数据集(使用索引)
    • 事务模板重复(只修改输入参数值)
  • NewSQL 有更狭窄的定义:
    • a lock-free concurrency control schema
    • a shared-nothing distributed architecture

NewSQL的分类

  • 使用新架构的新系统
  • 重新实现2000s由Google等开发的中间层基础设施
  • 由云计算提供的数据库即服务

注:以上的这些之前都提出新的存储引起去取代mysql默认的innoDB,只改变引擎的话就不需要改变API,但是作者认为mysql的InnoDB可靠且性能好,如果改变InnoDB的存储引擎是为了将行存换成列存,如OLAP的话是可以接受的(如Infobright,InfiniDB)。但还是OLTP事务的话换掉InnoDB引擎是没有什么意义的。

新的架构

  • 都有以下几个特征:
    • 基于分布式架构在shared-nothing resources,且包括以下组件:支持多节点并发控制、冗余容错、流控制、分布式查询处理,且包括节点之间的查询优化和交流协议(如节点和节点之间直接send intra-query data,不需要经过统一的中间层)
    • DBMSs都自己管理他们的主要存储(无论是在内存还是在磁盘上),不依赖HDFS等系统,这个特性是为了实现query落在数据节点,减少传送代价。
    • 当然也有缺点,新的架构想必采用了新的技术,但对于这些技术大多人都不熟悉,那对应的管理数据库和报告工具也就还没有啦~针对此,Clstrix和MemSOL和MYSQL wire protocol维持兼容性。
  • 本类案例:Clustrix, Cockroach, Google Spanner, H-Store, HyPer, MemSQL, NuoDB, SAP HANA, VoltDB.

透明的分表中间件

  • 分表的特性:
    • 每个节点都跑同一个数据库
    • 每个节点仅是数据库的一部分
    • 每个节点都不能被应用独立访问
  • 中间件组织查询,安排事务,管理每个节点的数据分布、复制、分割。
  • 有个shim layer装在每个数据库节点上和中间层交流,它主要负责代表中间件去执行本地的查询并返回给中间件结果。
  • 中间件的优点:使用人员都感觉使用的是同一个节点的数据库。
  • mysql就使用中间件去扩展,因此中间件需要支持mysql wire protocol
  • 很多组织的确是使用了中间件,但每个节点都使用传统的数据库(如mysq),这样他们都不能使用存储管理器或者并发控制schema。而且中间件不得不先去优化一下查询计划再分发给不同的数据库节点。(每个节点自己也会优化中间件派发给自己的查询)
  • 本类案例:AgilData Scalable Cluster, MariaDB MaxScale, ScaleArc, ScaleBase.

数据库即服务

  • 如今,很多云计算都提供NewSQL 数据库即服务,也就是开发人员不需要自己去配置资源等等啥的,只要会使用就好了。交付给用户的只是一个连接DBMS的URL,以及一个用于监控的仪表盘页面或者一组用于系统控制的API。
  • 本文只认为在2016年止只有两款可以认为是NewSQL,分别是Amazon’s Aurora(利用日志结构存储管理来优化I/O并发度)和ClearDB提供定制化的DBaaS部署在主要的云平台上。【不太清楚ClearDB】

  • 本类案例:Amazon Aurora,ClearDB

NewSQL的新技术

主存存储器

  • 基于内存存储的NewSQL DBMS有学术的(H-Store,HyPer)也有商用的(MemSQL,SAP HAHA,VoltDB)
  • 将数据库全部存储在内存上实质在1980s就被提出来了,那个时候,PRISMA/DB(首个分布式内存DBMS也被开发出来了),Altibase,Oracle’s TimesTen,AT&T’s DataBlitz是其组件。
  • 基于内存存储器的NewSQL新就新在它可以将数据库的一部分(比如冷数据)驱逐到磁盘中,也就是说基于内存存储器的NewSQL也可以支持比内存大的数据库了。
    • 实现这个通用方法是使用一个数据库内部的internal tracking mechanism来挑选出冷数据。
    • 此外,还有一个方法是EPFL中使用VoltDB的OS虚拟内存页。
    • MemSQL,管理器手动创建数据库去以列存的方式存储table。它以log-structured storage方式去减少update的开销。

分库分表

  • 最早的分布式数据库是SSD-1 project 1970,在1980s system R和INGRES也创建了各自的分布式版本,前者是一个shared-nothing,基于磁盘的分布式数据库,后者由于它的动态查询优化算法得以出名,它把分布式查询切割成小块。
  • 但以上分布式数据库都没有啥进展有以下两点原因
    • 机器太贵了,分布式机器代价大
    • 那个时候由于应用都很简单,对分布式高性能的数据库没什么追求。
  • partition怎么做?
    • 将数据库的table水平分到几个节点中,可以根据数据的columns,或者具体的values(如根据一个customer的id,做个range or hash partitioning分在节点中,然后对应的order啥的也根据id进行划分,这样尽可能保证一个事务在一个节点上进行查询,避免分布式事务),但是Amazon Aurora,ClearDB去不支持这样的partition【为啥呢】
    • 据库schema可以转换为树状结构,树的后代与根具有外键关系。然后依据这些关系关联的属性对表进行分区,使得单个实体的所有数据都能位于同一分区。例子:一个树的根节点可能是一个客户表,数据库将会根据每一个客户进行分区,将每个人的订单记录和账户信息存放在一起。
  • 有两种cluster node架构,分别是同质的和异质的
    • 同质:数据和执行都放在一个节点上。
    • 异质:数据和执行节点分离

异质节点架构

NuoDB

  • 存储节点(SM):将数据库分为多个blocks(atoms)

  • 事务引擎节点(TEs):作为atoms的内存缓冲

    • 需要write-locks on tuples,然后对tuples的修改都会去广播给其他的TEs和SM
    • 为避免nodes之间的来回,NuoDB公开负载均衡schema确保使用的数据会驻留在同一个TE中
    • 和其他的分布式数据库一样都需要partitioning schema,但不需要pre-partition数据库以及定义table之间的关系(为啥不需要?)

MemSQL

  • 只具备执行功能的聚合器节点和存储实际数据的叶节点

  • execution-only aggregator nodes:不缓冲任务数据

  • 存储真实数据的叶子节点:会执行部分queries,从而也减少返回给aggregator节点的数据。而在NuoDB中SM就只是存储数据的节点。

实时迁移

  • 物理资源会迁移数据,和NoSQL中的re-balancing很像,但在迁移的过程中NewSQL会确保事务的ACID。有两个方法保证实现这点。
    • 以粗粒度的虚拟(逻辑)分区来组成数据库 分布在不同的物理节点上。当DBMS需要re-balance的时候,就移动节点之间的这些虚拟分区。
      • Clustrix(NewSQL),AgilData(NewSQL),Cassandra(NoSQL),DynamoDB(NoSQL)就使用这个方法。
    • 执行细粒度的re-balancing通过range partitioning重新分配tuples和tuples组。很像MongoDB中的auto-sharding feature。ScaleBase和H-Store常用这方法。

并发控制

  • 需要保证原子性和隔离性
  • 主要有两种协调器:集中式或去中心化事务协商
    • 集中式的:由一个协调器节点专门管这个事情,所有事务操作都要经过它。在1970-1980s的TP monitors这个方法就被提出了
    • 去中心化的:每个节点都保持一定的事务状态(访问其节点数据的),节点之间会相互协商来避免并发事务冲突。
      • 优点:便于scalability
      • 缺点:需要记录DBMS节点的时钟来保证高同步,从而生成全局有序的事务。

分布式架构

2PL

  • SSD-1 由中心化的协调器管理shared-nothing nodes。
  • IBM’s R*是去中心化协调器协调的,它使用了分布式的2PL协议,这样事务可以锁定正在访问的节点中的数据项。
  • INGRES的分布式版本使用去中心化的2PL以及中心化的死锁检测。
  • 现在基本所有NewSQL都避开使用2PL,使用多版本时间戳排序。

MVCC

  • MVCC既确保事务之间的竞争,也允许long-running,read-only事务不会阻塞writers。
  • MemSQL,HyPer,HAHA,CockroachDB使用这个协议,他们对这个协议也各自做了工程上的优化和调整

2PL&MVCC

  • 修改数据库的时候需要去获取锁,修改完一条记录,那么为该记录创建一个新版本,使只读查询可以避免请求锁,因此不会阻塞写事务。
  • MySQL’s InnoDB,Google’s Spanner,NuoDB(在MVCC基础上引用了gossip 协议在各节点之中广播版本信息),Clustrix.
  • Spanner(及其后代F1和SpannerSQL)使用硬件设备(如GPS,原子时钟)来确保高精度时钟同步
  • CockroachDB使用混合时钟协议,结合松散 同步硬件时钟和逻辑计数器
  • 所有的中间件和DBaaS服务都继承了它们底层DBMS架构使用的并发控制方案,因为大部分都使用MySQL作为底层DBMS,所以大部分的都是使用的2PL加上MVCC方案。

TO

  • VoltDB
    • 安排事务在每个分区中一次只执行一个
    • 使用混合架构:去中心化方式安排单分区事务,中心化协调器对应多分区事务
    • 通过逻辑时间戳对事务进行排序,然后调度它们以便在轮到它们时在分区上执行
    • 不足:当事务横跨多个区时,由于网络的交互延迟导致节点等待message的时候空闲。

二级索引(辅助索引)

  • 次级索引包含来自表的不同于其主键的属性集。它允许DBMS支持主键和分区键以外的快速查询。

  • 分布式数据库中二级索引的challenge是他们不能总是像其他的数据库一样以相同的方式进行partition(如直接根据主键进行partition了)。

  • 在分布式数据库中支持二级索引的两个设计思想:
    • 二级索引存在哪儿
    • 如何在事务中维持二级索引
  • 中心化的协调器
    • 二级索引既在协调器节点,又在shard nodes。
    • 优:整个系统中只有单个版本的index,维持起来很方便
    • 劣:修改的时候需要修改所有节点上的副本。
  • 去中心化的协调器
    • 所有基于新架构的NewSQL都是去中心化的,且使用划分好的二级索引
    • 每个节点都存储index的一部分。
    • 优:修改的时候只需要修改一个节点
    • 劣:查询的时候需要去横跨多个节点去找数据在哪儿
  • Clustrix:既有replicated,粗粒度的(range-based)index在每个节点上,允许查询使用一个属性(并非partitioning属性找到合适的节点);各个节点上又有第二partitioned index,能根据index找到该节点的tuples。但是都是ranges,而不是单个的值,减少了保持索引副本在集群中同步所需的调度次数。【没太理解】

复制(冗余)

结点间数据一致性

  • 强一致的事务,事务的写入必须必须在被确认提交(即持久化)之前被确认并安装到所有副本上。需要使用原子提交协议(2PC)
    • 优点:事务读起来方便,各个结点都满足一致性
    • 缺点:开销也太大了吧,如果有一个节点失败了,或者网络分区延迟,系统就停着不动了。

两种不同传播的执行模型

active-active 复制

  • 每个副本结点都同步执行相同的query

active-passive 复制

  • 先在单个结点处理请求,然后将DBMS所得状态传送到其他副本
  • 大多数NewSQL DBMS都用这种方式,因为它们使用非确定性并发控制方案。(因为它们可能在不同副本上以不同的顺序执行,并且数据库的状态将在每个副本处出现分歧。因为执行顺序取决于很多因素,包括网络延迟,缓存停滞,时钟偏差等。)
  • 确定性DBMS(例如,H-Store,VoltDB,ClearDB)不执行这些附加的协调步骤。因为它们保证事务的操作在每个副本上以相同的顺序执行,从而保证数据库的状态相同。

通过广域网WAN来进行复制

  • 因为会引起延迟,所以一般采用异步复制。
  • NewSQL系统中只有Spanner和CockroachDB能提供广域网上强一致副本的复制方案。Spanner使用了原子钟和GPS来做时间同步,而CockroachDB使用的是混合时钟方案。

恢复机制

  • 保证数据的更新不会丢失,最小化停机时间

  • 操作:

    • 当主节点崩溃时,系统将会自动提升某个从节点充当新的主节点
    • 而之前崩溃的主节点重新联机后,需要从新的主节点或者其他副本中更新自己的数据,弥补在停机这段时间内缺失的数据。

两种方法恢复

  • 复的节点仍然从自身的存储中加载最后的检查点和写入日志,然后从其他节点读取缺失的日志部分。
  • 节点重新联机时丢弃其检查点,让系统给它另一个新的检查点,然后从这个点开始恢复(系统中加入新的副本节点时也可以用同样的机制。)

未来趋势

HTAP

  • 分析新数据和历史数据的组合来进行知识推断,获得洞察力

三种方法

分别构建OLAT和OLTP数据库

  • 前端的OLTP DBMS存储所有由事务创建的新数据,而在后端,系统使用ETL(extract-transform-load)工具将数据从OLTP DBMS导入到另一个后台的数据仓库DBMS

  • 所有在OLAP系统中产生的新数据也将会被推送到OLTP库中。

Lambda架构

  • 使用单独的批处理系统(例如,Hadoop,Spark)来计算历史数据视图,同时使用流处理系统(例如,Storm,Spark Streaming)来提供输入数据视图

HTAP数据库

  • 前两种方法的问题:

    • 数据传输时间开销大
    • 部署和维护两种不同DBMS的管理开销巨大
  • HTAP:结合了最近十年来在OLTP(例如,内存存储,无锁执行)和OLAP(例如,列式存储,矢量化执行 )领域的技术积累,而且只需要一个DBMS。

  • HTAP例子:

    • SAP HANA:在内部使用多个执行引擎,一个用于更适合事务的行数据,另一个用于更适合于分析的列数据。
    • MemSQL:使用两个不同的存储管理器(一个管理行,一个管理列),但是混合在同一个执行引擎中。
  • OLTP转HTAP例子:

    • HyPer将H-Store(OLTP)切换到MVCC的HTAP,可以支持更复杂的OLAP查询
    • VoltDB将OLTP性能转向提供流式语义【不清楚流式语义】

总结

  • NewSQL系统的采用率相对较低,因为NewSQL DBMS的设计目标是支持事务性的工作负载,而这些应用大多数是企业应用(这些比较保守)
  • 巨头们更愿意在自己的系统上进行改进和创新,而不是去收购初创的NewSQL公司。2014年Microsoft在SQLServer上新增了内存Hekaton引擎来增强OLTP处理能力。Oracle和IBM的创新进度比较慢,他们最近才为系统添加了列存储扩展,与新兴的OLAP DMBS(例如HP Vertica和Amazon Redshift)展开竞争,并有可能在未来推出内存中的OLTP工作负载处理系统。

image-20200827155826028

查询优化

Posted on 2020-08-05

数据库系统实现第四章(查询执行)、第五章(查询编译器)笔记

查询处理器

  • 查询处理器的主要部分

    image-20200726201722939

  • 查询编译概貌

    image-20200726201736827

  • 每个操作符的算法的选择是将逻辑查询计划转变为物理查询计划过程中的一个必不可少的部分。

查询执行

物理查询计划操作符介绍

  • 扫描表:

    • 读一个关系R的所有元组,无论是表-扫描或是索引-扫描
  • 排序-扫描:

    • 若排序的属性a上有B树索引(B树索引是有序的吗?不是按照key值吗,key是属性a的值吗)或R是按a排序的索引顺序文件来存储的时候,可以直接对索引进行扫描即可得到所需排序的R。
    • 若R很小,可以装进内存,那么可以使用表扫描或索引扫描得到元组,再使用主存排序算法
    • 若R大,无法装进内存,通过多路归并得到排序好的R。
  • 物理操作符计算模型

    • 使用磁盘I/O数目作为操作符的“代价”
  • 衡量代价的参数

    • 关系R的所有元组所需的块的数目B(R)
    • 关系R中的元组的数目 T(R)
    • 关系的一个列中不同值的数目V(R,a)
  • 实现物理操作符的迭代器

    • 迭代器是三个方法的集合:Open(),GetNext(),Close()
    • 使用迭代器时,同一时刻活跃的操作就有很多,元组只需要在操作符之间传递,无需将每个操作符得到的整个结果存放在磁盘或内存中。

一趟算法

  • 至少一个操作对象能完全装入内存

一次单个元组操作的一趟算法

  • 例子:选择和投影操作

image-20200727164357896

  • 因为输出缓冲区可能是其他操作的输入缓冲区,因此不把它算在所需空间内。
  • R如果一开始在磁盘上(可能从其他操作过来),那么代价就是执行一个表-扫描or索引-扫描所需代价。

整个关系的一元操作的一趟算法

  • 例子:分组操作符和去重操作符

消除重复

  • 第一次看到该元组就将它复制到输出并且加入缓冲区中。

  • 若缓冲区中存在该元组,就不必输出。为了加快判别,通常维护一个具有大量桶的散列表或者某种形式的平衡二叉查找树,可将散列表的存储开销忽视。

  • 注:R中不重复的元组的block数要<= M(内存缓冲区的块数)

    image-20200727170533716

分组

  • 在主存中为分组属性的每一个值创建一个项,该项包括:分组属性的值和每个聚集的一个或多个累计值。
    • Min(),Max()函数,保持最小值或最大值即可。
    • Count(),为组中见到的每个元组加1
    • SUM(),增加非NULL属性a的值
    • AVG(),总和&个数
  • 直到扫描最后一个元组后,才开始为分组操作创建输出,故这种算法不适合迭代器结构,因为要求在Open方法的时候必须将全部分组做好(不实际)
  • 同样用一个内存数据结构在已知分组属性值找到分组的项(散列表&各分组的项)
  • 一般,关系R都没有聚簇,故读取R的全部元组需要进行T(R)次I/O

二元操作的一趟算法

  • 例子:除了上方的操作之外的都可以归为这一类,如并、交、差、连接和积的集合形式以及包形式

  • 以下假定,R是两个关系中较大的一个,将D放在内存中。

  • 集合与包的区别:集合操作自动消除重复,包操作是不消除重复的

集合并

  • 将S读到内存的M-1个缓冲区中建立一个查找结构,查找关键字是整个元组,现将S的元组都复制到输出。然后一次一块将R的每一块读到第M个缓冲区中,对于R的每一个元组t,观察t是否在S中,若不在,也将t复制到输出。

集合交

  • 跟并类似,但t若在S中,复制到输出。

集合差

  • R-S:检查R中每一个元组t,若t不在S中,将t复制到输出。
  • S-R:检查R中每一个元组t,若t在S中,从主存中S的副本中删掉t,考虑完R的每一个元组后,将S中剩余的那些元组复制到输出。

包交

  • 将S中每一个不同的元组与一个计数联系起来,其初值是该元组在S中出现的次数。读出R的每一块,对于R的每一个元组t,观察t是否在S中出现,若出现,且与t对应的计数为正值,那么输出t并将计数减1.

包差

  • S-R:依次读取R的每个元组,若t在S中出现,则将与之对应的计数递减1,最后将内存中计数时正数的每一个元组复制到输出,复制的次数等于其计数。
  • R-S:依次读取R的元组t,若t不在S中出现,则将t复制到输出,若t在S中出现,查看t对应的计数c的当前值,若c=0,则将t复制到输出,若c>0,则不将t复制到输出,但将c值减1。

积

  • 读取R中的每一块,对R中每一个元组t与主存S(M-1个缓冲区)中的每一个元组连接,形成后即将其输出。输出所占空间很大,且处理R的每一个元组所耗的时间很长。

自然连接

  • 将R(X,Y)与S(Y,Z)连接。
    • 读取S的所有元组,构造一个以Y的属性为查找关键字的内存查找结构(M-1个缓冲块中)。
    • 将R的每一块读到第M个缓冲块中,对于R的元组t,利用查找结构找到S中与t在Y的所有属性上相符合的元组与t进行连接后形成一个元组输出。

嵌套循环连接

  • R(X,Y)与S(Y,Z)连接,R在内循环,S在外循环,假定B(S)<=B(R)[外层循环中使用较小的关系略有优势]

  • 没有必要要求有一个关系必须能装入内存

  • 基于元组的嵌套循环连接:

  • 改进:在R的连接属性(Y)上建立索引,便于查找元组。

  • 基于元组的嵌套循环连接的迭代器

    image-20200728213534782

  • 基于块的嵌套循环连接算法

    • S作为外层循环,可能B(S)>=M,那么需要将S分多次迭代。
    • R作为内层循环,每次读入一个块,依次将块中元组和缓冲区的S元组做连接,输出结果。
  • 嵌套循环连接的分析:

    • 代价与两个关系的大小(blocks数)的乘积再除以M得到的商成比例

总结

image-20200728214802020

基于排序的两趟算法

  • 数据先被读到内存处理了一下之后再写回磁盘,然后重新读取磁盘完成操作。
  • 以下假定B(R)>M,将R分成大小为M的chunk并排序。

两阶段多路归并排序(2PMMS)

  • 有一个子表的概念,子表不能超过M-1个(缓冲区数为M个),假定R占用B个块,因为每个子表可以包括M个块,于是子表数目为B/M,要求B/M <= M-1。

  • 阶段1:将R中的元组放入M个缓冲区中,利用主存排序进行排序,将排序得到的子表存到外存外【保证每个子表(最多M个)是有序的】

  • 阶段2:将排好序的子表进行归并(选择每个子表最前面的块读入M-1个缓冲使用归并进行排序)

    image-20200728220718306

利用排序去除重复

  • 与2PMMS的阶段1一样,就是在阶段2时,不断复制每一块的第一个未考虑的元组t到输出并忽略与它相同的所有元组,即将输入快中所有的t删除。

利用排序进行分组和聚集

  • 与2PMMS相似
  • 阶段1:用分组属性作为排序关键字,对每M块排序
  • 阶段2:查找分组属性的最小值,将该最小值v成为下一分组,然后为这个组计算出聚集值即可。

基于排序的并算法

  • 与2PMMS相似
  • 阶段1:创建R与S的排序子表
  • 阶段2:为R和S的每个子表使用一个内存缓冲区,在缓冲区中找元组t,复制到输出,并且从缓冲区中删除t的所有副本。

基于排序的交和差算法

  • 除了t的副本什么情况下复制到输出缓冲区有所区别之外,其他都一样。

基于排序的一个简单的连接算法

  • 先将R和S都使用2PMMS根据连接值进行排序(假定只有一个连接键)
  • 阶段1:R和S个占一块缓冲区,剩下的M-2都用来装连接值为y的所有元组

  • 代价:5(B(R)+B(S))次磁盘I/O,B(R)<=M^2且B(S)<=M^2,用于连接的属性具有公共的值的所有元组必须能全部装入M个缓冲区中。

一个更有效的基于排序的连接

  • 当连接属性具有公共的值元组不多的时候,可以将排序的第二阶段和连接本身合并。
  • 区别:为R和S创建大小为M的排序的子表

总结

image-20200731225846330

基于散列的两趟算法

  • M个缓冲区,将关系R分到M-1个桶中,每一个桶和一个缓冲区联系起来,当一个缓冲区满了,就将它写到磁盘并且初始化另一个块。
  • 上致跟上面都差不多..

缓冲区管理

  • 之前的操作都假定可以获得数量M的内存缓冲区,但实际上缓冲区很少预先分配给操作符,是由缓冲区管理器来进行统一分配的。

缓冲区管理结构

  • 有两个主要的缓冲区管理结构
    • 缓冲区直接控制内存(缓冲区只有内存部分)
    • 缓冲区在虚拟内存中分配空间(一部分缓冲区还在磁盘上,但是我们不关心),这情况下换进换出多了,会抖动。
  • 一般,DBMS初始化时,都会先设缓冲区的数目(作为一个参数)。

缓冲区管理策略

  • 跟操作系统中的调度策略一样…
  • 查询处理的内存管理:
    • 在某些DBMS中,内存是在多个缓冲池中(具有不同目的),有些是用来存放磁盘页面,有些是用来存放散列表。
  • 最近最少使用(LRU)
    • 缓冲区管理器保持每个块最后一次时间访问的表
  • 先进先出(FIFO)
  • “时钟”算法(第二次机会)
  • 系统控制
    • 针对“被钉住的”块(有其他指向它的块),缓冲区管理器都不能驱除它。
  • 这节没怎么仔细看..

使用超过两趟的算法

  • 这节没看..

查询编译器

基础与索引

Posted on 2020-08-05 | In 数据库系统实现
  • 包括数据库系统实现第一章、第二章、第三章(索引)

数据库管理系统成分

image-20200724142035493

  • 分为两大块主要模块:查询响应和事务处理

查询响应

  • 先由查询编译器对查询进行分析和优化(如检查语义和语法是否正确、构建语法分析树),选择物理逻辑计划
  • 得到查询计划后,传给执行引擎
  • 执行引擎向资源管理器请求记录or关系的元组
  • 资源管理器掌握着存放关系的数据文件、文件中的数据格式和记录大小,以及支持对于数据文件中的元素进行快速查找的索引文件。查找数据的请求被传送给缓冲区管理器
  • 缓冲区管理器与磁盘交互(以磁盘块 单位)

事务处理

  • 分为两个主要部分

并发控制管理器

  • 负责保证事务的原子性和孤立性

日志和恢复管理器

  • 负责事务的持久性

辅助存储管理

存储器层次

image-20200724143448491

组织磁盘上的数据

  • 一般,一个磁盘块中仅存放一个关系的元素

定长记录

  • 下图假定所有字段必须以一个4的倍数的字节开始

image-20200724150344115

image-20200724150409109

  • 当存取或修改记录时,记录(与整个块一起)就被移进主存
  • 块首部包含:
    • 与一个或多个其他块的链接
    • 关于这个块在这样一个网络中所扮演的角色的信息
    • 关于这个块的元组属于哪个关系的信息
    • 一个给出每一条记录在块内偏移量的“目录”
    • 指明块最后一次修改和/或存取时间的时间戳
  • 记录长度为316字节,假定4096字节的块,会有292字节的浪费

块和记录地址的表示

  • 内存中:与虚拟内存地址相关
  • 二级存储器中:与磁盘的设备ID,柱面号等等相关

客户机-服务器系统中的地址

  • 服务器:为客户端进程提供二级存储器数据,数据处于数据库地址空间,表示地址的方法有:
    • 物理地址(字符串):
      • 存储所连接的主机
      • 块所在的磁盘或其它设备的标识符
      • 柱面号
      • 磁道号
      • 块号
      • 块内偏移量
    • 逻辑地址
  • 客户端:其地址空间看作主存本身

指针混写

  • 把块从二级存储器移到主存储器中,块内指针可以“混写”,即从数据库地址空间转换为虚拟地址空间

image-20200724153804351

被钉住的记录和块

  • 即内存中一个块当前不能安全地被写回磁盘

image-20200724154305211

变长数据和记录

变长字段的记录

  • 当address地址为NULL时,直接在指向的指针空间处放一个空指针,进一步减少空间。

image-20200724154657714

具有重复字段的记录

  • 法一:

image-20200724155032593

  • 法二:
    • 保证记录定长,有效对记录进行搜索,但增加 磁盘I/O数目

image-20200724155045741

  • 不能装入一个块中的记录

image-20200724155711393

  • BOLB(二进制大对象)

列存储

  • 适用于:大多数查询请求是针对所有数据或者列的大部分数据。(常用于“分析型”查询)
  • 可以与值一起保存元组ID号~

记录的修改

插入

  • 元组以某个固定次序存储(如按主键顺序存储)
  • 插入的两种方法:(使用偏移量加速找到插入的位置)image-20200724162909062
    • 在“邻近块”中找空间
    • 创建一个溢出块

删除

  • 在记录处放删除标志

    • 可以是偏移量表中的空指针
    • 可以用删除标记代替记录,只用到第一个字节,后续的字节可用于另一个记录~

    image-20200724164311442

###

索引结构

基础

  • 主索引&辅助索引:主索引(主键)能确定记录在数据文件中的位置,而辅助索引不能

  • 索引类型:顺序文件(稠密索引、稀疏索引)、B树索引、散列表索引。

  • 稠密索引:为数据文件中的每条记录设一个键-指针对。其中所索引快保持键的顺序与文件中的排序顺序一致。(记录时排好序的)

  • 稀疏索引:为数据文件中的每个存储块设一个键-指针对。(假定数据文件排好序)【只会是主索引】

  • 多级索引:索引文件占据多个存储块,可采用多级索引【主索引】

  • 辅助索引:总是稠密索引,因为不是主键索引(如果该column也不是unique的),那就存在多个相同的索引内容,索引数据跨越多个块。使用辅助索引比使用主索引可能需要多得多的磁盘I/O,但无法解决!

    • 避免键值重复:使用桶的间接层

    image-20200725220045067

    image-20200726143152340

  • 辅助索引的运用:

    • 被组织成顺序文件的关系(如上都是)

    • 作为“堆”结构的主键索引(不太能理解)

    • 聚集文件

      1
      2
      3
      4
      5
      6
      7
      8
      Movie(title,year,length,genre,studioName,producerC#)
      Studio(name,address,presC#)

      Select title,year
      From Movie,Studio
      WHERE presC# = zzz AND Movie.studioName = Studio.name;(假定这是该应用场景典型的查询)

      为这个两个关系建立一个聚集文件结构,在查询键presC#上建立索引。

      image-20200725221051780

B树索引

  • B-树根结点块是永久地缓冲在主存中的绝佳选择。

散列表

  • 插入时,若没有位置,就存储到该块链上的某个溢出块中。

  • 删除时,若块中前一条记录被删除,就一条记录需移动到前面。

    image-20200726151506740

可扩展散列表

  • 动态散列表之一

  • 引入间接层,用一个指向块的指针数组来表示桶,而不是用数据块本身组成的数组来表示桶。

  • 指针数组能增长,长度总是2的幂。

    image-20200726152253294

  • 通过判断i和j(右上角小块中的)的大小,不断加倍桶数组,且分裂数据块。

  • 优点:若桶数组小到可以存放在内存中,那么访问桶数组就不需要进行磁盘I/O。

线性散列表

image-20200726153509875

  • i(当前被使用的散列函数值的位数)、n(当前的桶数)、r(当前散列表中的记录总数)
  • (没怎么看懂)
  • 优点:桶的增长较为缓慢

多维索引

  • 数据结构:类散列表方法,类树方法

多维数据的散列结构

  • 网格文件:通过排序该维的值来划分该维

image-20200726161359875

  • 当数据分布性很好,且数据文件本身又不太大,那么可以选择网格线。

  • 分段散列:为每个二进制位设定一个属性

    image-20200726162116830

    • 对最近邻查询或范围查询实际上没有什么用,因为点之间的物理距离并没有通过桶号的接近反映出来。
    • 如果只需要支持部分匹配查询,只需要指定某属性的值而不指定其他属性,那么分段散列函数可能会比网格文件好。

多维数据的树结构

  • 多键索引

    image-20200726162746159

  • kd-树

    image-20200726162909353

  • 四叉树:根据象限来划分

    image-20200726163747603

  • R-树(内部结点对应于某个内部区域)

    • 对于”where-am-I”这类典型查询,R树是有用的。

    image-20200726164316027

位图索引

  • 每条记录作为二进制位,针对年龄这个字段,如18岁,假定有6条记录可能在第1,2,3条记录的年龄为18岁,则位图表示为111000
  • 压缩位图:采用分段长度编码

注: 一般做删除操作,都直接在数据文件中采用“删除标记”

skywalking适配mysql

Posted on 2020-08-05 | In skywalking

背景

  • 为了去抓取应用端发来的负载信息,比如sql,timestamp,sql中的para,和select语句的result集合,通过分析这些负载,来模拟负载,主要用于抓取应用端的负载,相当于数据挖掘中获取数据的来源把~~

  • 这篇主要是总结我在适配skywalking获取mysql应用端的负载遇到的问题和感受。

先行

  • 利用skywalking在以mysql为数据库的应用程序中抓取负载,在实验中,以oltpbench为应用端。大致的配置是,在https://github.com/apache/skywalking拉去skywalking源代码,利用说明文档进行编译

    1
    2
    3
    4
    5
    git clone https://github.com/apache/skywalking.git
    cd skywalking/
    git submodule init
    git submodule update
    ./mvnw clean package -DskipTests
  • 编译好的在dist目录下,如果没有别的需求,可直接在启动应用端的脚本或命令行中加入-javaagent /skywalking/agent/skywalking-agent.jar。

  • 由于项目中需要按照一定的形式将抓取到的日志输入固定的文件中,因此主要对skywalking的三个包进行修改,分别是mysql-common,mysql-5.x,jdbc-commons,这三个都在./apm-sniffer/apm-sdk-plugins中。

操作

mysql-commons

  • 里面都是一些截流器,有针对预编译sql的PreparadStatementExeucute,还有PreparadStatementBatchExeucute,和普通的StateExecute。这些截流器都被注册了,与mysql-5.x中的注册器对应,注册器指明mysql中哪里函数利用那些截流器去捕获。如”add batch”函数就利用PreparadStatementBatchExeucute去抓取。”executeUpdate”利用PreparadStatementExeucute和StateExecute去抓取(根据不同的sql类型)

mysql-5.x

  • 一些注册器,与拦截器对应即可

jdbc-commons

  • 主要是加了connId,还有与commit,rollback有关的拦截器,在这个包中,也进行了修改。

问题

mysql 的 jdbc重复调用问题

  • 查看Mysql的jdbc的包(可利用反编译软件进行查看),发现add batch又调用了executeUpdate函数,导致skywalking抓包的时候重复捕获一条语句,导致重复。此外,还有executeUpdate自调用三次,导致一条日志被打印出三次。这类问题的处理方式,利用查看调用栈,分析它的调用过程,来忽略一些日志的输出。

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    Exception ex = new Exception();
    StackTraceElement[] ste = ex.getStackTrace();
    boolean fromExecuteBatch = false;
    for (int i = 0; i < ste.length; ++i) {
    if(ste[i].getMethodName().contains("executeBatch")||ste[i].getMethodName().contains("executeUpdate$Original")){
    fromExecuteBatch = true;
    break;
    }
    }

mysql中以一个host为一个connId

  • 由于项目的需要,我们需要得到connId,在jdbc-commons的相应位置加上与connId相关的代码。
  • 但是发现createstatement有个问题,就是无论多少个线程,以及无论多少个连接,但输出总是一个相同的。但从mysql端捕获到的connectionInfo都是不同的,后来发现是skywalking中是根据host和Port来存储connectionInfo的,若从相同的host和port发送数据库请求,那skywalking(mysql部分,oracle应该不是这样的)就认为是用一条connectionInfo信息,导致出错。
  • 这个问题的解决方法:就不用host和port进行存储..换了另一种方式。

总结

  • skywalking适配mysql耗时达1周左右,发现自己还是畏惧源码的阅读,无论是skywalking还是mysql-jdbc还是不能有效的进行阅读,希望下次能改进。
  • 自己对于问题的解决不能深入,抱着懒散的心态~,要加油呀!

SQLCheck: Automated Detection and Diagnosis of SQL Anti-Patterns

Posted on 2020-07-20 | In 论文

Motivation

  • 数据库即服务(DBaaS)目前很流行,云计算的出现,让很多开发人员都直接使用云上数据库而不用自己去搭建一个数据库,这扩展了数据库的使用,但很多开发人员没有数据库相关知识,可能写出来的sql语句存在APs(Anti-Patterns),而APs会影响访问数据库时的性能,进而对应用产生影响。因此,这篇文章站在这个角度,去检测sql语句是否存在APs,并且将sql中存在的APs进行排序(这里主要是为了修复主要影响性能的APs,因为修复APs可能修改数据库schema等等,会对其他的sql产生一定影响),最后对主要的APs进行自动修复(实质上这篇文章是按照现有的规则进行修复)。

Challenge

  • AP可能违反基本数据库设计原则(如,参照一致性等等)

Contribution

  • 讲述了如今其他识别APs的工具的局限性

  • 注意:detection是有按照一定的rule进行匹配来将AP侦测出来

  • Detection:将query和data分析相结合进行AP侦测。

  • Rank:针对APs上的性能数据进行建模,获取rank model。

  • Fix:基于规则query重构技术提出fix APs的建议。

Background

Classification of Anti-Patterns

image-20200717144713076

Impact of Anti-Patterns

  • Performance:性能,如吞吐和延迟
  • Maintainability:当业务发生了改变,应用设计和组件被修改的容易程度(这里指sql和schema)
  • Accuracy:存进去的数据和读出来的时候是否还是一致的(如,浮点数的精度是否丢失了,考虑数据库schema的column类型定义的如何)

System Overview

image-20200717175237267

  • ap-detect:静态分析queries,分析数据库中的数据和元数据
  • ap-rank:根据detect出来的AP对各类评价指标的影响排序(文中设置user-study,由于可以根据自己的应用需求调整不同评价指标的权重,如读事务多的应用场景对读性能更为看重)
  • ap-fix:根据定义好的rule来对AP进行fix(也就是说rule是有限的,无法cover到全部,这里detect从后面的实验来看也应该是有限的AP,就是定义的AP越多识别出来的也越多…)

Finding Anti-Patterns

  • Query-Analyser:获取query的column name、table names、predicates、constraints和indexes等等(就是一些logical feature)
  • Data-Analyser:获取数据库中表的每个Column的数据分布和format(类型?)等
  • Query-Rules:根据建立好的rules识别APs判别query是否存在APs
  • Data-Rules:根据建立好的rules识别APs判别data是否存在APs

image-20200717180220192

Query Analysis

  • intra-query detection:从单条sql获取context,使用预定好的rule(rule里由一系列函数组成)去detect,使用no-validating parsing logic来支持不同数据库的查询,返回annotating the parse tree(ap-detect和ap-fix使用这个去找到APS)
  • inter-query detection:从sql和sql之间获取context,利用整个应用的context,不一定是相邻的,在 Intra-query上多包涵了两个组件:schama和与应用相关的queries

Data Analysis

  • 首先scan数据库收集【收集代价大,定期执行】:
    • tables的schemata
    • 数据在相关column上的分布(e.g., unique values,mean, median等等)
  • 还是根据相应的规则去check构建好的context中是否存在APs

Ranking Anti-Patterns

Metrics for Ranking Anti-Patterns

  • Read and Write Performance (RP, WP):读写性能。通过如果修复好这个AP能获取多少倍的加速。这个指标作为rank依据。
  • Maintainability (M):可维护性 是根据支持新的task时,数据库 在存在这个AP和不存在这个AP需要重构时改变的Number的差异,当number高度依赖于应用中的queries数时,这个AP优先级就会很高。
  • Data Amplification (DA):冗余的列,如age和出生年月;各种冗余不必要的信息。
  • Data Integrity (DI): 更新是否保证数据库中保存的是想要的数据
  • Accuracy (A): 如是否满足参照一致性

Model for Ranking Anti-Patterns

  • 运用开发人员根据自己的开发需求去设置上方metrics的权重。(实际上开发人员也很难去做到这个,这里可以做一个权重自动化设置工具)
  • 当APs之间发生冲突时,即修复一个AP会影响恶化另外一个AP,那就选择优先级高的AP进行修复

Fixing Anti-Patterns

  • 自动推荐合适应用场景的数据库设计和queries。

image-20200720130345206

  • 两部分的query需要transform: 1. 具有APs的部分 2. 修改APsquery会影响的部分query
  • 如果产生模糊的转换,那就返回一个textual fix,就是说这个工具不足够帮你fix…那它告诉你啥textual fix呢,让开发人员自己看着做
  • 绿色部分解析: 如果query transformation清晰,那就把它解析成语法树,之后转换成sql语句。(数据库的语法树解析感觉有时间可以看看)

Query Repair Engine

  • rule system是可扩展的,开发人员可以自己把rule按照一定的要求加进去。
  • 首先,规则系统范式使得ap-fix很容易利用修复规则之间复杂的触发交互,从而避免了显式布局流的需要 规则之间的控制(这里没看懂,就直接有道翻译了一下)

Rule Representation:

  • 每条规则都包含一个detection function和一个action function

Implementation

  • 提供了三个接口:

    • Interactive Shell:

      1
      2
      3
      4
      # Import the anti-pattern finder method
      from sqlcheck.finder import find_anti_patterns
      query = `INSERT INTO Users VALUES (1, 'foo')`
      results = find_anti_patterns(query)
  • REST Interface

    1
    2
    HTTP POST /api/check
    Body: {"query":"INSERT INTO Users VALUES (1,'foo')"}
  • GUI Interface
  • 扩展性

    • 通用的规则接口(name, type, detection rule, ranking metrics, and repair rule)
    • context builder:增加应用的context来支持复杂rules
    • 用DBMS-specific解析器代替no-validating解析器

Evaluation

  • 与DBDEO进行比较(Digital Equipment Corporation. 1992. SQL-92 Standard.

    https://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt.)

Detection of Anti-Patterns

  • AP-coverage
  • accuary
  • Dialect-Coverage:可以适用哪些DBMS

Ranking and Repair of Antipatterns

  • 针对几个类型的AP进行讨论
    • 索引过度使用
    • 索引使用不足
    • 不存在外键
    • 枚举类型(只有那几个数值)

User Study

  • 招募23个学生去
    • construst SQL queries
  • 使用GUI 界面追踪这些信息:
    • the original SQL queries
    • the fixes suggested by sqlcheck for the APs detected in the original queries
    • the re-formulated SQL queries developed by the user that incorporate these fixes.
  • Web Applications & Databases
    • 收集github上的sql query,检测人家的应用的query是否存在APs,若存在就在别人的issues中提建议或是给别人发邮件,看看 别人的回馈意见。
  • Limitations And Future Work
    • 都是根据定好的rules来发现APs的,对于新的不在规则中的APs不能后发现

TOREAD

  • Tushar Sharma, Marios Fragkoulis, Stamatia Rizou, Magiel Bruntink,and Diomidis Spinellis. 2018. Smelly relations: measuring and understanding database schema quality. In Proc. of ICSE. ACM, 55–64.
  • [21] Cunningham & Cunningham Inc. 2014. C2 Wiki. http://wiki.c2.com/?AntiPatternsCatalog

对负载生成的启发点

  • 分析数据特征的时候,获取data在相关列上的分布情况,如Unique values,mean,median等(这里lauca貌似没有使用这些特征)

研究的主要方向

  • 与SQL Anti-pattern有关,找到、排序(该APs对性能产生影响的大小)、修复APs

各项性能指标

  • Read and Write Performance (RP, WP)
  • Maintainability (M)
  • Data Amplification (DA)
  • Data Integrity (DI)
  • Accuracy (A)

基本知识

数据库即服务

  • DBaaS是一种云计算服务模型,用户只需要访问数据库即可,无需设置物理硬件,安装软件或配置性能。
  • Schemate即schema的复数形式,包括table、column、data type、view、stored procedures、relationships、primary key、foreign key等

Adjacency List

  • 具有层次结构的数据

  • 解决方法:邻接表、路径枚举(Path Enumeration)、嵌套集(Nested Sets)、闭包表(Closure Table)

    • 邻接表:在树中检索指定节点的祖先节点是很昂贵的
    • 路径枚举:将祖先存储成字符串(以路径的形式),缺点:数据库不能强制规定路径是正确形成的,或者路径中的值对应于存在的节点。维护路径字符串取决于应用程序代码,并验证它的开销是非常昂贵的。

    img

    • 嵌套集:根据深度优先额外维护nsleft和nsright,便于寻找节点的所有祖先节点和所有的孩子结点,但插入和移动节点很复杂,需要重复编号nsleft和nsright,当树的使用设计频繁的插入,嵌套集不是最佳选择。

      img

    img

    • 闭包表:多增加一个表结构,专门用来存所有的祖孙信息,不只是父子信息,更便于查询。

    img

MYSQL 必知必会

Posted on 2020-07-15 | In 基础书本

基础知识

使用MySQL基本指令

  • use database1; 切换数据库
  • SHOW DATABASES; 显示所有数据库
  • SHOW TABLES;
  • SHOW COLUMNS FROM customers ; === DESCRIBE CUSTOMERS;

limit关键字:

  • Limit 3,4 ==LIMIT 4 OFFSET 3; 从行3开始,返回4行;检索出来的第一行是行0

ORDER BY

  • 通常ORDER BY子句中使用的列将是为显示所选择的列。但是,实际上并不一定,用非检索的列排序数据是完全合法的。
  • 默认是升序
  • 对于文本性的数据进行排序时,A被视为与a相同,这是MySQL(和大多数数据库管理系统)的默认行为。但是,许多数据库管理员能够在需要时改变这种行为。

使用IN操作的优点

  • 语法更清楚且直观
  • 一般比OR操作符清单执行更快
  • 最大优点是可以包含其他SELECT语句,使得能够更动态地建立WHERE子句。

MySQL中NOT

  • 支持对IN、BETWEEN和EXISTS子句取反,这与多数其他DBMS允许使用NOT对各种条件取反有很大的差别。

SQL中的谓词

  • 谓词与函数的区别:对于通常的函数来说,返回值有可能是数字、字符串或者日期等,但是谓词的返回值都是真值(true/false/unknown)。

  • LIKE、BETWEEN、IS NULL、IS NOT NULL、IN、EXISTS

    • LIKE——字符串的部分一致查询(模糊查询)

      1
      2
      3
      4
      5
      6
      7
      ①前方一致select * from user where username like 'aaa%';

      ②中间一致select * from user where username like '%aaa%';

      ③后方一致select * from user where username like '%aaa';

      %可以匹配0个字符。
    • BETWEEN(and)——范围查询

用通配符的技巧

  • 不要过度使用通配符,注意通配符的位置。

MySQL的正则表达式

  • REGEXP和LIKE的区别:LIKE匹配整个串而REGEXP匹配子串

  • 不区分大小写,为区分大小写,可使用BINARY关键字

    1
    WHERE prod_name REGEXP BINARY 'JetPack .000'
  • 进行OR匹配 ‘|’

  • 匹配几个字符之一 [123] 表示匹配1或2或3,与1|2|3不同,前者是[1|2|3]的缩写

    1
    2
    3
    4
    SELECT prod_name
    From products
    WHERE prod_name REGEXP '[123] Ton'
    ORDER BY prod_name;
  • 匹配范围 [1-3]

    1
    2
    3
    4
    SELECT prod_name
    From products
    WHERE prod_name REGEXP '[1-3] Ton'
    ORDER BY prod_name;
  • 匹配特殊字符,如 . [] | () ,用\\为前导,如\\.表示查找. \\也用来引用元字符

  • 匹配字符类

    image-20200618114655099

匹配多个实例

  • 对匹配的数目进行更强的控制

    image-20200618114850214

    匹配定位符

  • 为了匹配特定位置的文本

    image-20200618115227926

    • ^的双重用途:

      • 在集合中[],用它来否限定该集合

      • 用来指串的开始处

创建计算字段

拼接:

  • 多数DBMS使用+或者||来实现拼接,MySQL则使用Concat()函数来实现。

    1
    2
    3
    4
    5
    Select Concat(vend_name,'(',vend_country,')')
    From vendors
    ORDER BY vend_name;

    Return: ACME(USA)
  • RTrim()函数: 删除数据右侧多余的空格。如RTrim(vend_name)

  • LTrim()函数:去掉串左边的空格

  • Trim()函数:去掉串左右两边的空格

  • 取列的别名

使用数据处理函数

  • 以下的函数都是大多数SQL实现支持的。

文本处理函数:

  • 其中SOUNDEX()考虑了类似的发音字符和音节,使得能对串进行发音比较而不是字母比较。

image-20200620111648327

image-20200620111657883

日期和时间处理函数

  • MySQL使用的日期格式,不管是插入或更新表值还是用WHERE子句进行过滤,日期必须为格式yyyy-mm-dd。

image-20200620112323444

数值处理函数

  • 在主要DBMS的函数中,数值函数是最一致最统一的函数

    image-20200620112642455

汇总数据

聚集函数

image-20200620112834932

  • Distinct关键字:后面必须使用列名。

分组数据

  • 使用WITH ROLLUP关键字,可以得到每个分组以及每个分组汇总级别(针对每个分组)的值

    1
    2
    3
    SELECT vend_id,COUNT(*) AS num_prods
    FROM products
    GROUP BY vend_id WITH ROLLUP;
  • WHERE过滤行,HAVING过滤分组

联结表

  • 笛卡尔积:由没有联结条件的表关系返回的结果

  • 内部联结,也称为等值联结

    • ANSI SQL规范首选INNER JOIN语法,而不是=

      1
      2
      3
      SELECT vend_name,prod_name,prod_price
      FROM vendors INNER JOIN products
      ON vendors.vend_id = products.vend_id;

乱七八糟

  • 没有主键,更新或删除表中的特定行很困难,因为没有安全的方法保证只涉及相关的行。
  • MySQL在执行匹配时默认不区分大小写。根据MySQL的配置方式,搜索可以是区分大小写的。
  • 可移植的:能运行在多个系统上的代码
  • 可伸缩性:能够适应不断增加的工作量而不失败。

Head First Java

Posted on 2020-07-15 | In 基础书本

基本知识

  • 两种变量:
    • primitive主数据类型
    • 引用变量(其值位于堆上)【相当于遥控器】
  • 对象:状态(实例变量 instance varible)、行为(方法 method)
  • 主要在类中使用封装 (set 函数) 来隐藏数据
    • 将实例变量标记为private, 将get/set方法标记为public
  • 实例变量永远都会有默认值,但局部变量未被初始化 使用时被给出error,即其没有默认值
    • integers 0
    • floating 0.0
    • boolean false
    • reference null
  • 变量的比较:
    • 使用==比较两个primitive 主数据类型,或者判断两个号|用是否引用同一个对象。
    • 使用 equals()来判断两个对象是否在意义上相等。(像是两个 String对像是否带有相同的字节组合)

构造器与垃圾收集器

栈与堆

  • 对象在堆上,类中的实例变量(实质上是对象的一部分)自然也在堆上
  • 局部变量和方法调用在栈上,对象引用变量与primitive主数据类型变量都是放在栈上

构造函数

  • 当类中手动写了一个带有参数的构造函数时,编译器不会主动帮你写一个无参数的构造函数,因此需要自己写!!
  • 使用this()从某个构造函数调用同一个类的另外一个构造函数。this()只能用在构造函数中,且必须是第一行语句。super()与this()不能兼得。
  • 、

The ArtScience and Engineering of Fuzzing: A Survey

Posted on 2020-07-13 | In Test Case Geneation

20200713 15:01 结

  • 关键词:自动化软件测试,模糊化,软件安全
  • 目的:作为一个survey,围绕模糊化,给它下定义,总结对软件测试提出的模糊化方面的改进,发掘有哪些创新点
  • 领域: 软件测试,模糊化

基础知识

定义

  • 模糊化是什么?
    • 使用生成的输入(输入存在语义和语法错误)重复运行一个项目。
  • 目前模糊化有哪些问题?
    • 一些fuzzer工具的源代码和手册实际达不到描述的那样
    • 不同fuzzer工具使用的术语各大相同
  • Fuzzing定义
    • 从fuzz输入空间生成样例测试Program,并突出PUT(Program Under Test)期望的输入空间
  • Fuzz Testing定义
    • 使用fuzzing技术去测试看是否PUT违背安全政策
    • 目的:找出program中影响安全的bugs
  • Fuzzer定义
    • 在一个PUT上执行fuzzing testing的Program
  • Fuzz Campaign
    • 针对一条特定安全政策,一个fuzzer在PUT上的一个特定的执行,相当于专门针对哪个安全,制作出一些sample去用fuzzer执行。
  • Bug Oracle
    • 作为fuzzer的一部分Program,检测给定的PUT执行是否违反特定安全政策
  • Fuzz Configuration
    • Fuzz算法的参数配置,依赖于特定的fuzz algorithm
  • 设计测试工具的时候,一定先熟悉源代码和PUT的相关知识!!!

Fuzz Testing 算法

  • 有两个部分:对配置进行预处理;迭代(包括Schedule,InputGen,InputEval,ConfUpdate,Continue)
    • PREPROCESS:执行大量操作,比如插入一些功能性代码到PUTs中,或是检测种子文件(产生测试样例)的执行速度
    • 第二部分的迭代的流程:先选择一个fuzz配置;根据配置中的参数生成测试样例;用测试样例和oracle bug检测是否违背安全政策(这个应该可以自己规定),这时可以得到execinfos,这大概是为了变动配置,为了之后能选取到更具有代表性的配置去生成测试样例;根据execinfos,改变fuzz配置;最后判断fuzz配置是否进行下一轮的迭代。

Fuzzer的分类

  • 根据在每次fuzz run的时候fuzzer观察到的东西多少,以下只是安全专家的一致认同,在实际使用的时候,三者的区别不太明显。

  • 黑盒fuzzer

    • 只能看到PUT输入和输出的表现,有一些还考虑输入的结构信息
  • 白盒fuzzer
    • 可以观察到PUT的内部信息以及执行过程中的收集到的信息
  • 灰盒fuzzer
    • 可以观察到一部分PUT的内部信息和它的执行,但是不能得到PUT完成的语义,且只能对PUT执行轻量级的分析和对执行收集动态信息。即收集一些近似信息

PREPROCESS

  • 预处理包括对PUT做一些性能监控(灰盒、白盒都能去PUT中获取一些反馈信息)[对PUT进行插桩],去除冗余的配置(像种子选择),修剪种子,生成驱动应用。

Instrumentation

  • 白盒、灰盒中用来收集最有价值反馈的一种方法,代码插桩(在被测程序中插入完成相应工作的代码,即代码插桩技术,来获取程序中可执行语句被执行(即被覆盖)的情况)
  • 分为static instrumentation和dynamic instrumentation,前者一般在源代码的编译阶段执行,后者一般在运行阶段执行。

Execution Feedback

  • 灰盒fuzzers将执行反馈作为输入去优化测试样例,AFL等文章计算分支覆盖率作为反馈内容,但容易发生分支冲突,对此CollAFL提出相应解决方法。

In-Memory Fuzzing

  • 为了最小化执行开销,每次fuzz迭代只fuzz一部分的PUT,program会保留PUT的快照,下次fuzz新的测试样例时需要恢复memory快照。这种快照可以避免执行不必要的启动代码。
  • in-memiry API fuzzing通过一个函数而不是每次迭代恢复PUT的状态,这种方式尽管有效,但是找到的bugs却不完整,因为可能调用不到这种函数(我猜是函数名生成有问题??)

Thread Scheduling

  • 随机调度线程对找到race condition bugs很有效。

Seed Selection

  • 希望选取最小的种子集合最大化覆盖率(如节点覆盖率)
  • 覆盖率评价指标:
    • branch coverage(计算分支的执行次数),当测试样例在分支执行次数上的数量级不同时才认为它们是不同的
    • the number of executed instructions,executed branches,and unique basic block。希望将最长的执行路径的测试样例增加到minset中。

Seed Trimming

  • 在preprocess中执行,或作为CONFUPDATE的一部分

  • 在AFL中只要修改过的seed能够达到和原先种子一样的覆盖率,就修剪掉原先种子。

  • [177]发现size小的种子没啥用

Preparing a Driver Application

  • 给fuzzer一开始的时候准备一个驱动器(这里不太理解)

SCHEDULING

  • 选择一个fuzz 配置为下轮fuzz迭代,不同的fuzzer类型具有不同的配置。这里主要的研究点是提出创新性的scheduling算法。

The Fuzz Cofiguration Scheduling (FCS) Problem

  • 挑选一个可能产生最好结果的配置(评判可能依据 find the most number of unique bugs[unique bugs不知道咋翻译], maximize the coverage]。在挑选的时候考虑explore(关于每个配置获取更为准确的信息)和exploit(获取好的结果),做这两者的trade-off。

Black-box FCS Algorithms

  • 黑盒用到的反馈信息:crashes和bug的数量毕竟执行时间
  • [225]提炼数学模型,WCCP/UW,由于反馈信息会随着配置结果变差,因此选择一些配置不会导致反馈decay。为了将crashes或bugs / time来修改反馈信息,目的是为了能更快速地进行配置(感觉是把time因素考虑进去)。

Grey-box FCS Algorithms

  • 灰盒用到的反馈信息:黑盒能用到的,达到的覆盖率等等
  • AFL认为执行最快,input最少的是fit
  • AFLFast在AFL基础上做了三点改进

    • 增加两条重要准则:
      • AFLFast喜欢被选中最少的配置
      • AFLFast喜欢最少选择的路径
    • AFLFast在AFL增加了优先级,替代AFL中的圆形选择
    • AFLFast每个配置被选中次数是动态改变的
  • AFLGo修改了AFLFast优先级的特征,目的是为了找到特定的程序位置。

INPUT GENERATION

  • 分为generation-based和mutation-based,前者是基于model的,后者是通过mutate seed。

Model-based (Generation-based) Fuzzers

  • 预定义或用户提供的模型
  • 推断模型可能发生在PREPROCESS阶段也可能在CONFUPDATE阶段
    • 在PREPROCESS阶段,在PUT中搜找可用的数据(如文字),去预测合适的输出
    • 在CONFUPDATE阶段,每次迭代更新model
  • 编译器模型(不太能理解这个模型)
    • 解析特定的文件格式

Model-less (Mutation-based) Fuzzers

  • 需要seed-based输入生成和白盒输入生成。
  • Bit-flipping:翻转固定/不固定数量bit位,用mutation ratio决定翻转多少数量的bit位。因此,找到一个合适的mutation ratio数值至关重要。
  • Arithmetic Mutation:将选择的字节序列视为一个整数,对整数进行处理(不太能理解)
  • Block-based Mutation:以block为单位,进行mutation
  • Dictionary-based Mutation:对具体的字符(数值)进行mutation(不太能理解)

White-box Fuzzers

  • 先使用白盒程序分析找到PUT的信息,用这信息去进行黑盒or灰盒fuzzing。

  • Dynamic symbolic execution:比灰盒和黑盒慢很多,因为它需要对PUT的每条指令进行插桩和分析,这方面的研究都聚集在如何减少它的代价方面。

  • Guided Fuzzing:先对PUT进行分析(静态or动态分析)来获取有用的信息;再利用这个信息去生成test case。这上面的研究一方面需要减少分析产生的代价。

  • PUT Mutation:不重要。。

INPUT EVALUATION

Bug Oracles

  • 有三个方面的侦测:内存安全问题(是否访问到不安全的内存、控制流的完整性[啥意思])、访问到未被定义的行为(如编译器不同,程序猿只考虑了某些编译器情况下可行,但有些不可行却忽略了)、输入的合法性(比如SQL访问可能对数据库引擎存在一些破坏)

Execution Optimizations

  • 由于迭代需要每次都初始化PUT进程,需要耗费大量的时间,对此,AFL提供了一个fork-server去让迭代去从进行初始化好的进行进程中fork一下。

Triage

  • 分析和报告导致违反政策(感觉就是不安全的)的进程,分为三步:去重复、优先级、测试样例最小化。

Deduplication

  • 去重复:若该test case返回的Bug已经被以前的test case找到了,这个test case就不要了。能得到test case集合,该集合中每个test case都能触发唯一的bug。去重复有三种主要的实现方式:
    • stack backtrace hashing
      • 记录了crash时的stack backtrace(如:main → d → c → b → a → foo ),当其他crash时的stack backtrace的后五个也是这个时候,认为他们重复, 这是major hash。而minor hash还考虑到line number(感觉是数量)。但这样做事基于一种假设,即相似的crash是由相似的bugs引起的,但这假设未被验证,且能举出反例。
    • coverage-based deduplication
      • 在PUT中插桩记录PUT每次执行的edge覆盖率,根据这个信息选取seeds,AFL认为当crash覆盖到之前未见到的edge或者未覆盖到之前在所有其他crashes中都覆盖到的edge时,认为该crash是唯一的。
    • semantics-aware deduplication
      • 从每个crash处反向分析,找到那个function,根据function来对crashes进行分类。(怎么那么奇怪)

###

Prioritization and Exploitability

  • 根据一个crash的可利用性来划分优先级。Microsoft’s !exploitable的优先级划分: EXPLOITABLE > PROBABLY_EXPLOITABLE > UNKNOWN >

    NOT_LIKELY_EXPLOITABLE,

Test case minimization

  • 利用bug oracle进行test case 最小化。许多fuzzers都针对自己特定的情况选用test case最小化算法。

CONFIGURATION UPDATING

  • 可用来区别是白盒fuzzer、黑盒fuzzer、灰盒fuzzer。由于黑盒只能用到Oracle bug(不能得到PUT的内部信息)大部分Conf都不被修改。

Evolutionary Seed Pool Update

  • 灰盒fuzzer大多基于遗传算法进行展开,EA-based fuzzers大多数使用node或者Branch覆盖度作为fitness function.[后面举例没仔细看]

Maintaining a Minset

  • 赋予favorable fuzzing conf以高的被选择进行fuzzing的权重。思想是:需要少的test case最大化coverage评价指标。

​

Links:

  • paper: https://ieeexplore.ieee.org/abstract/document/8863940

Detect logic bugs in DBMS的三篇论文

Posted on 2020-07-13 | In DBMS Testing

Testing Database Engines via Pivoted Query Synthesis论文

主要内容

  • 随机生成table和rows
  • 从每个表随机生成一行
  • 根据选择的rows随机生成表达式并评估结果
  • 修改表达式 直到返回真

领域

  • 检测logic bug,logic bug即是否返回正常的行

研究常用的方法

  • 差异性测试,不适用于所有DBMS

    image-20200618202218604

各项性能指标

  • 观察是否返回 随机生成的row

缺点

  • 不适用于大数据集
  • 可能只能做where里面的AST树

扩展知识点

  • AST树
  • 差异性比较

image-20200618202406294

Detecting Optimization Bugs in Database Engines via Non-Optimizing Reference Engine Construction论文

主要内容

  • 不正常的优化可能会导致logic bug

  • 核心:重写DBMS不能优化的潜在随机生成优化的query

  • 让DBMS不做优化,做全表的扫描

    image-20200618192500114

    • 左边是原本数据库会优化的,右边是数据库不会优化的。
  • image-20200618202756024

Ternary Logic Partitioning: Detecting Logic Bugs in Database Management Systems

主要内容

  • query分区,将一条给定原始的query,分成多份更复杂的queries,每个部分都计算结果的一部分。
  • 三元逻辑分区:

    • 基于一个布尔谓词p计算成True,False,NULL的观察
  • image-20200618192837917

image-20200618203712878

image-20200618203725136

Automated Grading of SQL Queries 论文解读

Posted on 2020-06-20 | In SQL Queries Paper

主要内容

  • 自动给学生的sql query打分,局部打分,通过判断错误严重的程度。

  • 采用 weighted equivalence edit distance metric,找到最小的编辑序列,能将原始错误的sql query转为正确的query。

  • 使用query规范化规则针对语法和语义进行规划

    • 语法,如将Not(A>B) 替换为A<=B; 将操作构建一棵flattened tree
    • 语义,将query中主键上的distinct移除,将query中冗余的关系移除。
  • Flattened Tree Structure

    image-20200620103146416.png

    • 将query中有连接关系的都flatten一下,转化为等价形式。
    • 针对flattened tree,谓词/投影/聚类操作都作为一棵棵子树
  • 计算规范化的编辑距离

    • 对于每个组件(子树)分别计算编辑距离,然后找到每个quert的带权距离。Σc∈componentsWc ∗ Ec
  • 根据编辑距离给分

领域

  • 指出错误sql query错在那个部分,也就是做最小的改动,能让sql query变成正确的。

研究常用的方法

  • XData通过比较正确query和学生query得到的结果,对学生 sql query进行二分类,即判别正确or错误,但太简单了,想得到更细致的。
  • 根据正确query和学生query返回结果交集所占正确结果的比例,但有可能因为一个很小的错误得出的结果很差,导致分数低。
  • 学生的sql query需要做多少个变化才能和正确的sql等价,但许多具有语义差异的sql在返回的结果却没什么差异。(本文)针对此,使用大量query规范化技巧移除学生和正确的queries的不相关的语法和语义差别。但是需要给出多个正确的queries,将学生query与其相比较,选出匹配度最高的query。这个问题可以抽象为图中找最短路径,提出一个贪心启发性技巧。

问题

  • 基于规范化编辑距离的给分有可能是不公平的,在规范化部分还存在一些问题。

实验部分和讨论部分

  • 随机创建一对不正确的学生queries,a和b,让两个志愿者对每对queries分类,第一类是a queriy的分高,第二类是b query的分高,第三类是a,b query的分数一样高。

  • potentially an infinite number of edit options are possible

对负载生成的启发点

SQL QUERY 规范化

  • B. Chandra, M. Joseph, B. Radhakrishnan, S. Acharya, and S. Sudarshan.

    Partial marking for automated grading of SQL queries. PVLDB (Demo),

    9(13):1541–1544, 2016.

Source Code

  • https://www.cse.iitb.ac.in/infolab/xdata
  • https://gitlab.com/xdata/xdata-web/-/tree/developer/XDataGrading/src
123
luyiqu

luyiqu

blog

28 posts
13 categories
27 tags
RSS
© 2020 luyiqu
Powered by Hexo
|
Theme — NexT.Pisces v5.1.4
访客数 总访问量 次
0%