SQL 抽象语法树

说白了,SQL语法树就是编程语言的抽象“翻译器”,将你的SQL语句转换成机器可以理解的模式树。
其实很简单,就是利用节点将SQL拆解成语法块,但是拆解的过程却暗藏玄机。

先说说最重要的结题(question)。
在我们去年运行的数百万个项目中,我们发现超过6 0%的SQL都在这个节点上。
比如去年Q3 的用户形象报告就是基于select、where、groupby加入的查询节点。
还有一点是节点(选择器)的选择。
我们去年就有这个洞。
数据表大小为3 000,如果直接用select提取所有字段,CPU立刻飞到9 0%。
之后,我们选择某些列并向下。
另一个是决定性的。
结耦合子句特别容易被忽视。
例如,在一个设计中,我一开始认为这是多余的,但后来我发现我错了。
数据透视表没有结果的原因是我忘记添加它应有的条件。

等一下,还有一件事。
错误选择desc/asc节点进行排序(orderby)会降低速度。
我们有一个财务报告计划,并将每一个订单都设置为 asc。
结果每次运行都要等半个小时。
更改index + desc优化后,立即快了9 0%。
说实话,这很令人不安。
很多人不注意这一点。

建议下次写复杂的SQL时,先画一个简单的AST,尤其是有连接或者子查询、绝对值的时候。

LSM树揭秘:NoSQL存储系统的核心

嘿,LSM 树怎么样?上周有位客户问我,启发了我去看看……2 02 3 年,我在上海一家商场给一位搞大数据的同学讲课。
他说LSM树只是一堆数据,没什么意思。

其实LSM树的核心就是“日志结构化”和“合并操作”。
日志结构化意味着数据像写日记一样被逐一添加。
顺序写入磁盘比随机写入快得多。
例如Kafka就采用了这种思想,消息不断地添加到文件中。
LSM 在树数据库中使用它。

但是仅仅添加是不够的。
时间长了再查数据会很麻烦。
所以它还有一个“合并操作”,就是定期合并那些分散的日志碎片,让数据更有条理。
想想看,如果每次搜索都要找到很多碎片文件,那速度会很慢。

NoSQL 数据库主要使用 LSM 树来实现快速写入。
将记录写入关系数据库可能需要更新多个页面。
LSM树直接放入内存中。
当内存满时,立即写入磁盘,效率很高。
例如LevelDB就是一个典型的例子。
分为几层(L0到L6 ),数据像喷泉一样一层层流下来。

写入过程如下:新数据前进到内存的C0层。
当内存满时,会触发合并。
数据按键排序然后写入磁盘的C1 层。
当C1 填满后,继续合并到C2 层...如果key重复,合并时会自动保留最新的key,旧的key会被移除。
这个合并操作是异步的,不影响写入新数据。

询问怎么样?先检查内存。
如果找不到内存,则逐层检查磁盘,直至找到。
尽管检查多个层可能是必要的,但在撰写本文时已经进行了大量优化,因此缓慢检查是可以的。

但是,LSM树也有缺点。
例如,在读放大中,你可能需要翻转磁盘的几层来检查一条数据;在写放大中,合并数据时必须对多个文件进行排序,这也是相当消耗资源的。
之前2 02 2 年调试过HBase,有一次集群突然卡住了。
经过长时间排查,发现数据合并到LSM树的时候CPU就爆炸了。

当前的优化方法,例如LevelDB使用布隆过滤器在每一层上构建快速搜索索引。
在检查数据之前检查是否需要检查该层。
还有一个层次结构。
并非所有层都混合和合并。
当上一层满了的时候,才会和下一层进行合并,这样就减少了资源消耗。

总之,LSM树采用内存+多层磁盘,实现快速查询还可以。
但用不用还是要看你的情况。
如果要写任务非常频繁,比如每秒几十万个,所以LSM树非常适合。
如果读操作很多,可能就得使用其他的优化方法。
无论如何,这取决于你。

SQLGlot:SQL解析神器,最大化/高效发挥SQL价值

上周一位客户问我如何更好地管理他们公司的数据库查询,尤其是涉及复杂 SQL 语句的查询。
我告诉他其实有一个工具叫SQLGlot,非常好用。
它不仅可以解析 SQL,还可以在不同的数据库方言之间进行转换,例如 DuckDB、Presto/Trino、Spark/Databricks、Snowflake 和 BigQuery。

我自己遇到的缺点是不同的数据库有不同的SQL方言,这是一个很头疼的问题。
例如,我想将 Presto 查询转换为 Spark,但发现很多功能不兼容。
但是SQLGlot可以帮助我们解决这个问题。
它可以在 2 1 种不同的方言之间进行翻译并格式化 SQL。

记得有一次,一位同事想要分析用户查询,看看哪些表被查询得最多。
我们使用 SQLGlot 分析了查询,发现了一个非常复杂的问题。
通过SQLGlot,我们轻松提取了字段名和表名,同时也发现了一些语法错误。

但是,SQLGlot也有其局限性。
有时,它可能无法在特定方言之间转换某些查询,在这种情况下,它会发出警告。
但总体而言,它的性能相当不错,尤其是用Python编写时。

我还在思考这个问题:如果有一天,我们想减少某些表的数据摄取频率,SQLGlot能否帮助我们分析哪些表已经很长时间没有被使用,从而节省云成本?是?我认为绝对可以。
不管怎样,你可以想象一下,这个工具还是蛮有用的。