QTech|区块链上的“SQL”
读趣百科>科普>金融财经

QTech|区块链上的“SQL”

导读

《F1:A Distributed SQL Database That Scales》是Google构建的用于支持广告业务的分布式关系型数据库系统。作为一个混合型数据库系统,它结合了高可用、NoSQL数据库的扩展性以及传统SQL数据库的一致性和可用性。F1数据库整体基于Google Spanner构建,Spanner主要为上层的F1提供了跨数据中心的数据复制功能和一致性保证。而F1通过使用结构化数据分层架构模型和合理的应用设计,来降低数据备份带来的延迟,并提供了全功能的SQL支持。该论文也成为很多厂商实现合约中的SQL功能的重要参考。

区块链执行SQL的可能性

业务系统中的数据是以结构化的组织存在,使用结构化语言查询可以极大提升业务人员访问数据的便捷性。

SQL(Structured Query Language,结构化查询语言)是一种特定目的的编程语言,广泛应用于关系数据库管理系统,例如大家所熟知的MySQL、Oracle等。SQL是高级的非过程化编程语言,它允许用户在高层数据结构上工作,不需要用户指定对数据的存放方法,也不需要用户了解其具体的数据存放方式,这种灵活的方式自然衍生出了很多优秀的SQL执行引擎。

以我们熟知的MySQL为例,其中就包括了InnoDB、MyIsam和Memory等执行引擎,不同的执行引擎之间各有优劣,在不同的使用场景上会发挥出不同的作用,但是其向上的表现却是一致的,由此我们衍生出了在传统区块链的基础上来构建高效可用的SQL执行引擎的设计思想。

存储引擎从很大程度上限制了执行引擎的实现,传统的区块链系统一般会采用键值对的NoSQL数据库,将产生的状态数据以键值对的形式进行存储,同时方便世界状态的计算。为了保证区块链底层的存储结构不发生大的变化,我们需要设计一个方式,尽可能将SQL执行引擎建立在键值对数据库之上。在Google的F1中本身就是基于NoSQL数据库进行扩展,这让在区块链上执行SQL有了一定的可能性。

然而问题在于,要想解决区块链上执行SQL语句,就必须要解决SQL语句的编译问题以及如何将SQL的结构化数据保存到KV数据库当中,这也是我们本篇分享的主要内容:SQL编译与数据存储。

SQL编译

同大部分语言一样,SQL编译主要是将SQL语言转化为AST(Abstract Syntax Tree,抽象语法树),然后才能基于生成的语法树来设计我们的执行引擎。

既然谈到了编译,必然离不开在编译原理中离不开的两个话题:词法分析和语法分析。

词法分析是将字符序列转换为标记(token)的过程;语法分析则是根据某种给定的形式文法对token构成的输入文本进行分析并确定其语法结构的一种过程,主要作用是进行语法检查并构建有输入的token组成的数据结构(一般是语法分析树、抽象语法树等层次化的数据结构)。

如果通俗的来讲,将编程语言的编译类比为自然语言,那么词法分析关注的是你说了什么内容,语法分析则是关注与你说的内容是不是正确的,是否能够让人理解的。

词法分析相对而言比较简单,语法分析则相对来说会复杂很多,笼统地说语法分析方法可以分为自顶向下分析算法和自底向上分析算法,两者的主要区别是一种是“扩展”,一种是“规约”,至于语法分析是如何工作的,此处篇幅有限不再过多展开介绍,读者可自行了解编译的语法分析方法,包括遇到歧义或要回溯时是如何处理的。

上述算法依据的语法规则一般称之为上下文无关语法,一个语法表达式一般会表达为S->AB的形式,将产生式左侧的符号称之为非终结符,代表可以继续扩展或产生的符号;只能出现在右边的称之为终结符,无法再产生新的符号。

BNF(Backus Normal Form,巴科斯范式)是一种用于表示上下文无关语法的语言,事实上很多编译器都是可以通过编写类似的语法表达式,用工具直接生成一个编译器,如Java编译器就是通过Antlr4来生成的。

尽管有现成的方式可以帮助我们生成编译器,但是完整的描述出SQL语言的语法表达式本身就是一件繁琐且工作量很大的事,索性我们能从很多地方获取到这个语法表达式文件,例如从MySQL官网可以获取到MySQL的语法表达式(因为“SQL方言”的存在不同SQL数据库语法表达式会略微不同),在现有的SQL语法表达式的基础上进行修改可以大大减少设计工作量。

CREATETABLEIFNOTEXISTStestTable(idbigint(20)NOTNULL,namevarchar(32)NOTNULL,expbigint(20)NOTNULLDEFAULT'0');

这是一个创建数据表的SQL语句,我们可以用这样的范式来表示我们的创建表的过程:

CREATE[TEMPORARY]TABLE[IFNOTEXISTS]tbl_name(create_definition,...)[table_options][partition_options]

如果范式中包含其他的子范式,当其被匹配到时,就会执行我们所期望的流程。

例如使用goYacc我们可以将我们定义的范式逻辑转化为一个golang语言的编译器,假设基于goYacc将其中一种创建表的SQL范式编写为如下:

CreateTableStmt:"CREATE"OptTemporary"TABLE"IfNotExistsTableNameTableElementListOptAsOpt{stmt:=$6.(*ast.CreateTableStmt)stmt.Table=$5.(*ast.TableName)stmt.IfNotExists=$4.(bool)stmt.IsTemporary=$2.(bool)$$=stmt}

其中$$表示的范式的最终返回值,$x表示的第x个位置的返回值,如$4表示的就是IfNotExists返回的结果,而AST的节点数据结构则需要我们事先定义好。

最终我们可以将上述创建表的SQL语句生成为一个AST的结构如下所示(忽略了name字段的展示):

当有了AST这个数据结构之后,就可以使用Visitor模式对树的每个节点进行访问,来获取我们想要的信息以及生成执行过程。

数据存储

通过上一小节,相信大家对SQL的编译以及AST有了一个基本的概念,现在来讨论另一个问题,如何将SQL数据存入到键值对数据引擎中。

主要分为:表信息存储、表内行数据存储以及索引存储。

▲ 表信息存储

对于数据表的信息,例如表名、行信息和索引信息等这些内容,可以将表结构以某种序列化方式转化为二进制格式来进行保存,键值对的key则可以为每个表生成一个唯一的表ID,来作为表信息的索引,当需要使用对应的表结构时,只需将其反序列化为表结构即可,相对来说表信息转化为键值对保存是比较容易的。

▲ 表内行数据存储

数据表内的行数据存储会复杂一些,以上述创建的SQL表为例,假设向其中插入的某一条数据的SQL语句如下:

INSERTINTOtestTable(id,name)VALUES(001,"tom");

首先,我们要确定这一行数据的key,可以将key的生成规则抽象的表示为:

tablePrefix_recordPrefixSep。

其中tablePrefix和recordPrefixSep都是固定前缀,用于标识表和行信息的开始,而TableID则为创建表时生成的唯一ID,对于行ID,当表内存在整数型的主键则会将这一主键值作为行ID,否则将同样会为改行分配一个唯一的行ID,由此一行数据的key可以确定下来。

对于一行数据的value,可以将每一列的数据紧凑的排列在一起即可,例如上述描述的插入语句的数据,用16进制来表示可以描述为01746f6d00,01表示的列id的值,746f6d表示的是列name的值(即"tom"),00则表示列exp的默认值,而这些数据的类型可以从表信息中获取到,无需保存在行的value中。

当然这样表示一行数据的value肯定是不够的,实际上还需要基于数据编码的基础上增加:版本号、该行内容包含的列数据数量、分别是哪些列的数据以及每一列的数据起始偏移等,附带上这些额外的信息后才是一个完整的一行数据。

▲ 索引存储

另一个比较关键数据就是对索引的存储,需要再次说明的是:对于一个表内的每一列信息,都会分配一个唯一列ID来进行标识。

索引主要分为唯一索引和非唯一索引两类:

唯一索引在存储时将索引值作为key,行ID作为value来进行索引信息的保存,具体的一个唯一索引key表示为:

tablePrefix_indexPrefixSep_indexedColumnsValue

indexPrefixSep同样为固定前缀,用于表示索引列信息的开始,所以一个完整的唯一索引信息key还包含了表ID和列ID。

非唯一索引在存储时将索引值和行ID组合未做key,value则保存空值,通过依赖于存储引擎在遍历时按字典序的特点获取到对应的非唯一索引下的所有行ID,具体一个非唯一索引key表示为:

tablePrefix_indexPrefixSep_indexedColumnsValue_rowID

同样的一个完整的非唯一索引key还包含了表ID和列ID。

综上,通过对于SQL编译处理以及SQL数据键值对存储,让大家可以大致的了解常见的SQL数据如何存储到键值对存储引擎中的设计理念。

小结

本文主要介绍了SQL的编译处理以及如何将SQL转化到键值对存储引擎的技术方案,引发了如何基于现有的区块链架构来执行SQL语句的思考,如何通过SQL执行来拓宽区块链的业务使用场景的实践。

但这远没有结束,此过程之中还有很多问题需要我们研究思考,例如如何进行外键关联,如何进行复杂的笛卡尔积查询以及如何合理度量SQL执行的复杂度。

同样需要注意的是,并不是所有的需求都适合于区块链,例如基于非索引的查询在目前的区块链系统中就显得很不合理,这需要存储引擎的的配合。

总的来说在区块链上执行SQL并不是不可能的,但需要我们不断的去探索一个合理的可以高效的在区块链上执行SQL功能的解决方案:更易用、更高效、更强大。

大家看了这篇文章如果有好的想法,欢迎在评论区与我们交流。

最新金融财经科普

比特币钱包查到IP吗?如何低风险从事比特币投资?

很多比特币玩家最近害怕了,因为他们担心“比特币钱包查到IP吗”这个问题。不知道从哪里传出来的消息,很多新朋友都在各种社区咨询比特币钱包查到IP吗?不少网友直接...
展开详情

usdt收币地址是什么?usdt转账时该注意什么?

你了解usdt收币地址是什么吗?将获取的usdt转入到正确的usdt收币地址当中,保证我们可以正确的进行usdt的转账。下面让我们对于该种货币的交易有一个更深层...
展开详情

比宝石星球好的挖矿软件是哪个?挖矿有哪些事项需要注意?

挖矿是可以让我们直接获得数字货币奖励的,所以现在很多人都非常的关注挖矿。比宝石星球好的挖矿软件很多人都想要了解,那么,比宝石星球好的挖矿软件是哪个?今天就来了...
展开详情

面对银行大放水,谁能从中获利?

谁能从法定货币中受益?印制法币的中央银行?投资法币的商业银行?受理法币的企业?还是持有法币的我们?针对这类问题,目前很有可能还无法找到合理答案,但在经济衰退临...
展开详情

Reddit的区块链奖励将于2021年迁移到以太坊网络

Reddit继续提供关于其区块链社区集成系统的更多详细信息,该系统将在移植到以太坊网之前在测试网络上运行。5月13日,Reddit正式公布了其社区积分系统,宣...
展开详情

香港有哪些数字货币交易所,该选择哪一个交易所?

香港有哪些数字货币交易所,其实在目前的投资利益链上,是不可以缺少的,紧紧连接着广大投资者和区块链项目方,所以很多人才想要知道香港有哪些数字货币交易所,通过安全...
展开详情

云算力有哪些坑?

有一些云算力商品会声称回报率高过200%。当然,在币圈混迹了这么久,我们也深知一个道理,投资不能只看收益,还要综合考虑。毕竟,云算力商品的坑也不少。首先的服务...
展开详情

区块链公司与印度政府合作以增加农民的收入

农业技术初创公司Agri10x计划通过使用区块链削减中间商,更好地将小规模农民与全球买家联系起来。如同当地新闻来源《商业标准》(BusinessStandar...
展开详情
热门推荐

2019年比特币能涨多高?为什么那么多人的预测都不准?

在2018年年底的时候,网络上有很多机构和投资人都在预测2019年比特币能涨多高。如今2019年已经过去,回头看看那些大神们所预测的2019年比特币能涨多高的...
展开详情

有什么因素会干扰到比特币现金的价格

比特币现金(BCH)既是一种数字虚拟货币,也是一种支付网络。比特币现金出现于2017年12月,是比特币硬分叉的结果,目的是增加可处理买卖交易的数量。比特币现金...
展开详情

比特币“数字黄金”的称号是不是真的没有了?

最近这一个月,想必许多 币圈朋友的心态都崩了,不光币价崩盘,更重要的是,比特币的一大故事“数字黄金”,看上去破灭了。这个月的起伏,超过了绝大多数人的想象,很早...
展开详情

央行区块链数字货币值得投资吗?如何选择数字货币币种好?

数字货币现在正处在一个高速发展的阶段,现在很多人都十分的看重央行区块链数字货币。今天我们就来了解一下央行区块链数字货币,让你知道这款数字货币是否是值得投资的数...
展开详情

BitMEX交易所比特币数量大幅下降

BitMEX在3月13日经历了大规模的比特币抛售之后,交易所中比特币数量出现了大幅的下跌。BitMEX目前约有244,000个BTC,较3月13日时市场峰值3...
展开详情