简单生活

  • 线性代数回顾(二)

    ·

    到目前为止,前面的线性方程组的解,还有一些问题没有彻底回答(例如,解空间的描述),在回答这个问题之前,我们需要先了解一下“向量空间”。“向量空间”的严格定义是有些枯燥的,这里暂时把“向量空间”的限制为大家所熟悉的、最为典型的“ \(n \) 维欧氏空间”。

    1. 向量空间

    1.1 基

    要描述一个向量空间中的元素,则首先需要一组基(坐标)。在\(n\)维欧氏空间,最为常见的一组基,即为多个“垂直”(“正交”)的单位向量,即:

    $$ \begin{align}
    \alpha_1 &= (1,0,\dots) \\
    & \vdots \\
    \alpha_i &= (\dots,0,1,0,\dots) \\
    & \vdots \\
    \alpha_n &= (0,\dots,1)
    \end{align}
    $$

    在二维平面空间中,则为:\( \alpha_1 = (1,0) \quad \alpha_2 = (0,1)\);三维空间则为:\( \alpha_1 = (1,0,0) \quad \alpha_2 = (0,1,0) \quad \alpha_3 = (0,0,1)\)。

    既然有“正交”基,那么当然有不那么“正交”的基,而此类“基”则是更为普遍的。事实上,更为普遍的,任何 \( n \) 个线性无关的向量都可以作为向量空间的基。

    1.2 线性相关与线性无关

    考虑一组向量\( \alpha_1,\dots , \alpha_n \),如果当且仅当所有\( a_i = 0 \quad i=1,\dots,n\)时如下的等式才成立:

    $$ a_1\alpha_1 + a_2\alpha_2 + \dots + a_n\alpha_n = 0 $$

    那么,就说 这组向量 \( \alpha_1,\dots , \alpha_n \) 是线性无关的。反之,则称这组向量是线性相关的。

    或者这么说,对于一组线性无关的向量\( \alpha_1,\dots , \alpha_n \):任何一个向量都不能用剩余的向量做“线性表示”。

    1.3 一些重要的结论

    结论:设\( \{ \alpha_1,\dots , \alpha_n \}\)是向量空间\( V \)的一组基,那么\( V \)空间中的每一个向量都可以唯一的表示为这组基的线性组合。这个线性组合的系数,就叫“坐标”(注:相对于这组基)。

    结论:\( W_1 \)、\( W_2 \)是\( V \)的有限子空间,那么有:

    $$ dim(W_1+W_2) = dim(W_1) + dim(W_2) – dim(W_1\cap W_2) $$

    结论:\( n \)维向量空间中,任意\( n \)个线性无关的向量都可以取做基。

    2. 线性变换与矩阵

    2.1 概述

    “线性变换”是指向量空间中一类特殊的映射 \( \sigma : R^n \to R^m \) ,需要满足条件是:

    • \( \sigma(\xi + \eta) = \sigma(\xi) + \sigma(\eta) \)
    • \( \sigma(a\xi) = a\sigma(\xi) \)

    “线性变换” 描述了向量空间之间的映射。后续所有的内容大概都是围绕此而展开,后续所有的内容都会尝试通过各种方式将 “线性变换” 的特性研究清楚。这里写出部分结论,后面再慢慢展开:

    • 线性变换之下,原点保持不变。即 \( \sigma( \vec{0} ) = \vec{0} \)
    • 几何意义下,通常,线性变换包括了:旋转、镜像、拉伸/压缩(特别的,有时候会压缩到零)、剪切

    为了研究清楚一个线性变换上述的特点,通常需要选取一组“基”,然后使用这组“基”的“坐标”来描述空间中的点,进而再描述对应的线性变换。最为常见的基为“正交单位基”。

    从方法上来看,研究清楚“线性变换”最为关键的是研究清楚对应的“变换矩阵”。所以,“线性代数”的核心后面就变成了对矩阵特性的研究,但是,也不要忘记了初衷,否则很快就迷失了。

    2.2 线性变换

    我在大学期间对于线性变换、矩阵有什么作用,是完全没有概念的。所以对于他们的特性研究也没有掌握的很深,基本上是停留在能够把一些联系题做对这个层面。而现在,注意线性变换的广泛应用之后,尝试去理解去本质之后,就会寻根问底的去理解清楚什么是线性变换、什么是矩阵。这里再次说说我的理解。

    在一个向量空间中,最为常见的是 \(n \) 维欧氏空间,会有很多的向量,例如每个 Embedding 就可以理解是在一个线性空间中,“线性变换”表述了是空间中的一类映射,该映射满足上述“小结2.1”中的两个要求,即原点依旧到原点、映射保持所谓的“线性”(例如,向量和的映射等于映射的和等)。

    在一个向量空间中,一个线性变换就是一个符合一定条件的映射。与向量空间的基的选取是没有关系的。自此,与矩阵也是没有关系的。所以,线性变换本身是更为底层、更为基础的概念。

    2.3 欧氏空间的线性变换与矩阵

    现在我们把问题限定在 \(n \) 维欧氏空间中。那么,这时候,我们如何描述一个线性变换呢?是的,就是“基”与“矩阵”。

    通常,\(n \) 维欧氏空间,我们会先选取一组基,然后使用一个矩阵去描述这个线性变换。并且非常幸运的,一旦这组基 选定了,这个矩阵是唯一的。

    结论:在\(n \) 维欧氏空间(这个条件似乎可以去掉)中,对于线性变换 \(\sigma \),如果选定一组“基”,那么就存在唯一的“矩阵”描述该线性变换。

    上述的结论,是比较明显的。我们考虑对于线性变换中的上述选定的基向量 \(\alpha_i,\quad \text{where } i = 1,\ldots,n \),线性变换将其映射到 \(\beta_i,\quad \text{where } i = 1,\ldots,n \),那么根据“基”的基本性质,对于这里的任何 \(\beta_i \)都可以表示成\(\alpha_i \)的线性组合,所有的这些系数构成的矩阵,就是上述描述的唯一的“矩阵”。具体的:

    $$
    \begin{aligned}
    \beta_1 &= a_{11}\alpha_1 + a_{21}\alpha_2 + \cdots + a_{n1}\alpha_n \\[0.5em]
    \beta_2 &= a_{12}\alpha_1 + a_{22}\alpha_2 + \cdots + a_{n2}\alpha_n \\[0.5em]
    &\ \vdots \\[0.5em]
    \beta_n &= a_{1n}\alpha_1 + a_{2n}\alpha_2 + \cdots + a_{nn}\alpha_n
    \end{aligned}
    $$

    即:

    $$
    \begin{aligned}
    \begin{bmatrix}
    \beta_1 & \beta_2 & \cdots & \beta_n
    \end{bmatrix}
    =
    \begin{bmatrix}
    \alpha_1 & \alpha_2 & \cdots & \alpha_n
    \end{bmatrix}
    \begin{bmatrix}
    a_{11} & a_{12} & \cdots & a_{1n} \\
    a_{21} & a_{22} & \cdots & a_{2n} \\
    \vdots & \vdots & \ddots & \vdots \\
    a_{n1} & a_{n2} & \cdots & a_{nn}
    \end{bmatrix}
    \end{aligned}
    $$

    即在这个线性变换\(\sigma \) 在选定基 \(\alpha_i,\quad \text{where } i = 1,\ldots,n \) 对应的矩阵为:

    $$
    \begin{aligned}
    A =
    \begin{bmatrix}
    a_{11} & a_{12} & \cdots & a_{1n} \\
    a_{21} & a_{22} & \cdots & a_{2n} \\
    \vdots & \vdots & \ddots & \vdots \\
    a_{n1} & a_{n2} & \cdots & a_{nn}
    \end{bmatrix}
    \end{aligned}
    $$

    从这段简洁的“证明”(或“说明”)来看,我们很自然有如下结论,根据空间中的“基”的选取不同,我们会得到不同的矩阵。因为我们反复会提到,我们经常会通过研究矩阵的特性来研究线性变换。那么,同一个线性变换在不同的“基”下的不同“矩阵”,很自然的能够想到,这些“矩阵”是有某些共性的,是的,我们称这些矩阵为“相似矩阵”,相关特性,暂不展开。

    3. 特征向量与特征值

    3.1 为什么

    为什么我们需要关注“特征值与特征向量”呢?为什么我们要去了解奇异值分解(SVD)呢?

    原因是“线性变换”是一个映射,是非常抽象的。而特征值 、特征向量、SVD分解可以把线性变换最为关键的特性,以非常“直观”的形式表达出来。当然,这里的“直观”并不是简单意义上能够一眼就看出什么来,事实上,“线性变换”本身就有很强的抽象性,这里的“直观”只是相对的,是否直观,完全依赖于各位看客自己的“悟性”了 。

    特征向量的基本定义:如果有 \( \sigma(\xi) = \lambda \xi \) ,那么这里的 \( \xi \) 就是特征向量,对应的 \(\lambda \) 就是对应的特征值。

    要想真正说清楚特征向量与特征值是需要非常多篇幅的,而且关于对特征向量的理解对于理解线性变化也是非常关键的,所以,建议花些时间较为系统的做一些理解。如果你已经建立的基础概念,这里的一篇文章可能是帮助你增强一些理解:特征向量与特征值。

    3.2 关于对特征向量的理解

    完整的讨论特征向量与特征值是复杂的,这里将其限定在一些较为简单的情况,作为一个入门。我们这里考虑最为简单的情况,即对于一个 \(n \times n \)的矩阵,其秩为 \(n \),并且在计算特征值时,有 \(n \) 是不重复的实数解,即没有任何根式重根。如果,恰好 \( n = 2 \)这大概是最为简单的情况了,不过理解这种情况,再进一步拓展,则学习曲线会平滑很多。

    我们来看一个实例,在二维空间中,在标准基下,我们有如下的线性变换矩阵:

    $$
    W = \begin{bmatrix}
    2 & 1 \\
    1 & 2
    \end{bmatrix}
    $$

    根据上述特征向量特征值的定义进行求解,我们可以有如下的特征值与特征向量:

    • \( \lambda_1 = 3 \) 特征向量 \( (1,1) \)
    • \( \lambda_2 = 1 \) 特性向量 \( (-1,1) \)

    从特征向量角度理解线性变换:那么上述的矩阵A对应的线性变换 \(\sigma \) 有如下特性,在这个二维空间任何向量 \(\beta \),都可以分解(投影)为上述两个特征向量方向的向量: \(\beta_1 \,, \beta_2 \),且有:\(\beta = \beta_1 + \beta_2 \)。那么,则有:\(\sigma(\beta) = \lambda_1 \beta_1 + \lambda_2 \beta_2 \)。即,这个线性变换可以这样描述:先将任何向量沿着特征向量方向分解,然后再按照特征值的大小进行拉伸或压缩,然后再把向量合并起来。

    上述的解释,可以对照着右图去理解。特征向量分别为 \((1,1) \) 和 \((-1,1) \) ,即图中浅绿色、浅蓝色方向。该矩阵作用在向量 \((0,1) \) 上,即图中的红色向量。先将红色向量沿着浅绿色、浅蓝色方向分解,然后按照特征值进行拉伸,即图中的绿色、蓝色向量,最后合并为图中的紫色最终向量。

    上述的场景是线性变换中,最为简单的一类。而实际的线性变换,则更为复杂,可能还涉及到对于向量的旋转、镜像、剪切等变换。关于更多场景可以自己探索,或者阅读相关书籍,也可以看看这篇文章中的更多直观的例子:特征值与特征向量

    “特征向量”可以很好的帮助理解“方阵”变换,还有一类变换时非方阵的情况,通常这时候可以借助于奇异值分解的方式去理解,关于奇异值分解可以参考:奇异值分解–深度学习的数学基础

    4. 最后

    初等的线性代数核心部分大概是这些内容,出于完整性的考虑,可以再进一步了解“Jordan 块”相关的内容,从而把相关理论补充完整,这里不再详述。

    如果再回到最初的线性方程组解的问题,我们这里就可以回答最后一个问题:对于一个线性方程组,如果有解,那么所有的解空间是怎样的?

    结论:如果方程组的系数矩阵的秩为\( r \),那么解空间的维度为\( n-r \)。解空间的“基”则可以通过初等变换求得。这里不再详述。

  • 新加坡之行

    ·

    这次到新加坡在工作之余,也好好的了解了一下这个城市,如下一些随意的记录吧。

    花园城市“新加坡”

    Rain Vortex@Changi Airport

    一到新加坡樟宜机场(Changi Airport)就可以看到一个精心设计的壮观“室内瀑布”(the Rain Vortex):

    the Merlion

    此外,这次参加展会的地点是 Marina Bay Sands的Convention Centre,这里是新加坡地标式建筑“Merlion”所在地:

    新加坡大概800年前被称为“Singapura”(马来语),意思是“lion city”,而更早之前,这里则是一个被称为“Temasek”的渔村。可以看到,“Merlion”的设计正是取自这两个名字所代表的意义。可以很好的代表这块土地过去千年的历史。

    Gardens by the Bay

    猜测,新加坡人的思路大概是,这个地方虽然不是很大,那我们就把这个缺点变成优点吧,于是,就把新加坡的每个地方都设计得非常精致。

    在滨海湾花园(Gardens by the bay)这里,就非常精致。这里,有一个地方叫“Flower Dome”,里面摆满了来自世界各地的植物、鲜花;旁边是一个“Cloud Forest”,里面也有一个非常高的室内小瀑布,里面则是一个以“Jurrasic Park”和“Jurrasic World”为主题的展览。

    关于“Singapore”名字的来历

    “Singapore”一词来自于马来语的“Singapura[1]”,一把认为这个词语最初是来自梵文,意义为“Lion City”。

    更为具体的,在梵文中,“Singa”来自梵文中的 siṃha (सिंह), 意思是 “lion”;而“pūra (पुर)” 意思为“city”,pūra也是很多印度地名非常常见的后缀(例如,Jaipur 斋浦尔)。

    那新加坡于“lion”有什么关系呢?根据记载,大概在800年前,“Sang Nila Utama”来到这里,看到了疑似狮子的动物,故就将此地命名为“Singapura”,即“狮城”。至于到底当时看到的是不是狮子,现在已经不可考了,主流的看法似乎倾向于认为是其他的大型猫科动物。但,这个名字已经叫了800年了,故到底是什么动物,已经不再重要了。

    在被叫为“Singapura”之前,这里是一个渔村,被称为“Temasek”,这词可能是来自马来语,表示“海边的地方”[1]

    “little india”

    这次后面几天住的酒店是在“little india”区,这里保留了很多印度文化相关内容。比较有代表性的是“India Heritage Centre”,有点像一个“印度文化博物馆”,而最近正好是“Deepavali”节日前后,所以在这个“博物馆”的楼下,就有一些印度表演,虽然在电视上也看过一些印度舞蹈,但是现场看,感受还是非常不一样:

    在“little india”区域中,另一个代表性的地方是一个叫“SRI Veeramakaliamman[2]”印度庙宇,这个神庙大约有150年的历史。

    文化的异同

    在新加坡众多感受之一是这里的“多元化”。在这里,多民族、多文化的融合做得非常好。

    即便是在一个族群里面,人与人或者人群与人群的差异都是非常大的。更不用说,感受上,不同的族群之间的差异了,大家的语言、文化、习惯、信仰、肤色差异都很大,天然的也就会让人与人之间产生隔阂。新加坡在对于这种隔阂的消除、弱化上做得很好。大家都说一样的英语,虽然也保留自己的母语、大家都住在一样的房子里面,在一样的地方上学与生活,最终,让彼此最大限度的相处在一起。

    在过程中,起初是感受到彼此的不同。而后,在印度神庙中,看到的大家脸上的对于诸神的虔诚,在哪里都是一样的;看到大家对于脱离痛苦的希冀,哪里都是一样的;看到爸爸带着孩子的介绍,孩子的好奇和父亲的关爱,哪里都是一样的;在India Heritage Centre为Deepavali表演的学生们脸上的自豪、兴奋与紧张,也都是一样的。

    Raffles@National Museum of Singapore

    周日,则去参观了新加坡国家博物馆。里面比较完整的介绍新加坡的历史。来的时候,已经注意到新加坡很多地方都以“Raffles”命名,包括最有名的酒店“Raffles Hotel”、“Raffles City”、“Raffles Institution”、“Raffles Place”等,而在国内也有一些高端的“来福士”商业中心。所以,参观时也特别留意了一下关于Raffles的介绍。

    Raffles 全名是“Sir Thomas Stamford Bingley Raffles”,他被认为是现代新加坡的缔造者,曾是现代新加坡建立时的“总督”,虽然他在新加坡的实际任期时间并不长(“His longest tenure in Singapore was only eight months, but he was considered the founder of Singapore nevertheless.”)。主要原因在于[3]

    • 他很早看到了新加坡地缘所具备的潜力,在当时,事实意义控制了“现代新加坡”
    • 制定了一系列具有现代化意义的城市规划与治理制度

    最终,影响了这里发展成为真正的“现代新加坡”。

    关于现代“Raffles”品牌

    我并不关注当前的商业现状,出于好奇做了一些搜索和阅读。众多“Raffles”品牌可能是属于“淡马锡控股”[4],而淡马锡则是新加坡政府的投资公司,淡马锡则控制了众多新加坡的重要公司,例如“星展银行”(DBS)、Seatrium、新加坡航空、凯德置地(CapitaLand)等。李显龙的妻子何晶曾担任淡马锡控股的CEO[4]

    Lee Kuan Yew

    Lee Kuan Yew 是当代新加坡国的实际建立者。关于他,已经有了很多中文资料,这里不再详述。

    Java, the island

    这次新加坡之行其中有两天去一趟 Jakarta-印尼的首都,位于Java岛的西北部。

    Java 真的是一个岛,而且非常大。Java 岛是印尼人口最多的岛,也是印尼首都雅加达所在的地方。但如果在 Google 上搜索“Java”会发现,这个词已经被编程语言所占据,真正的“Java岛”的搜索结果只在第三,并且,整个第一页,只有这一个结果是与Java岛相关的。

    不管怎样,Java 语言已经带火 Java 岛的咖啡。如果,你恰好在写Java,再来一杯Java,是不错的,如果你恰好是在Java岛上,那可能就完美了。

    参考链接

    • [1] https://en.wikipedia.org/wiki/Names_of_Singapore
    • [2] https://en.wikipedia.org/wiki/Sri_Veeramakaliamman_Temple
    • [3] https://en.wikipedia.org/wiki/Stamford_Raffles
    • [4] https://en.wikipedia.org/wiki/Temasek_(company)
  • This content is password-protected. To view it, please enter the password below.

  • 大概是在朋友圈看到的这个会议 GOSIM(Global Open-Source Innovation Meetup),注意到有来自HuggingFace、vLLM、SGLang、BAAI 、字节等开发者来分享,果断报名去学习。大会是周六、日两天大概有接近10个分会场同时并发分享,于是只能选择一些自己感兴趣的部分主题听听,本文是部分见闻记录与分享。

    推理优化与推理框架

    这次关于大模型“推理优化”相关的话题特别多,包括 vLLM、Llama.cpp、SGLang、🤗 Optimum、Chitu、kTransformers、llm-d 等。大模型要能够向企业或组织提供服务,除了通过 API (SaaS)的方式之外,最为常见的则可能是需要搭建一套具备高并发服务能力的平台,而这些平台则需要满足高并发、底层本、易运维等要求,这就是上述这些框架、工具所解决的问题。相关的研究和发展方向则集中在KVCache优化、网络优化、PD分离、容器化管理、量化效率提升、多硬件适配、国产化适配(Chitu)、expert deferral等。

    如果用数据库类比的话,这大概相当于各种 DBPaaS 平台如何通过调度、CPU硬件、网络设备去提升整理的数据库资源利用率。但是,LLM/VLM等所面临的问题,则更多的关注在 GPU (或与CPU协同等)层面。

    赤兔”定位是开源的「生产级大模型推理引擎」,面向于国产硬件环境做了很多适配,是一家“清华”背景的计算机专家推出的产品,背后的公司是:清程极智

    SGLang 是一个被比较广泛使用的大模型 大语言模型(LLMs)及多模态语言模型(VLMs)推理平台。该项目是LMSYS的一部分,目前似乎是以非盈利组织的模式在运作。该组织,最初是源自美国多所大学协作的项目(参考)。LMSYS 开发的其他著名项目包括:Chatbot Arena 、SGLang、FastChat、Vicuna LLM等。

    🤗 Optimum 是对 Transformer 库的扩展,目标是能够让模型能够更加高效在多种不同的硬件平台上高效的运行,包括训练和推理等。目前适配的硬件包括了NVIDIA、AMD、Intel、AWS Trainiu/Inferentia、Google TPUs、Habana、FuriosaAI,此外也可以非常方便与多个开源模型优化矿建进行集成,例如ONNX、ExecuTorch、Exporters、Torch FX。

    Second Me

    现在的大模型学习能力确实非常强,也许真的可以虚拟出一个“人”完整的“影子”。这个项目非常有意思,也获得了非常多个关注,项目的强调 “AI that amplifies, not erases, YOU.” 。项目的构想在于使用本地模型和存储,基于个人的数据、事件等构建一个数字的自己。也许现在的 AI 技术让这个设想有了某种可能性,这个项目则是对这种可能性的探索。感兴趣的可以关注:Second-ME

    Agents

    因为时间所限仅选择了部分 Agents 场次去听,包括“扣子空间”、“Google Agents”等。

    来自Google的开发者则非常系统的介绍了面向Agent,Google为整个生态提供了哪些能力,其实是几乎覆盖了整个Agent生命周期的,包括了 Agent 构建SDK、Agent之间通信、Agent托管等一系列完整的服务。Google 对于 AI 各个方向都是非常大的,并且整体都很成功,这大概也能够顺利的帮助 Google 从搜索时代过渡到 AI 对话时代。

    字节跳动的大模型(Seed)似乎还在“蓄力”阶段,但是上层的应用迭代和发展比较快。面相普通用户有“豆包”,面相开发者则有“扣子”,基于“扣子”,最近则退出了类似的“deep research”产品“扣子空间”。这次大会上,来自字节的工程师则分享了Agent、多Agent构建过程中的一些经验。此外也分享了一些有意思的“事实”:目前Agent领域发展非常快,在2024年初Agent基本上仅限于对话、陪伴机器人等少数方向;2024年底,智能客服则逐渐走向较为成熟的阶段;而现在则百花齐放,各个领域都在做大量探索,最为典型的就是“Manus”模式。

    OpenSeek

    OpenSeek 是一个比较新的、由 BAAI 发起的一个开源大模型项目,该项目致力于构建一个更加完整开源大模型项目,而不是仅仅开源模型架构和参数,而是提供更加完整模型构建过程的代码,从而向开发者提供更加“开放”的模型。此外,这次分享中,也介绍了一些 OpenSeek 的一些基础实现,例如mid/post training,此外特别提到了 OpenSeek 的 DMA 机制(Dynamic Mask Attention 通过动态计算部分Token的Attention,降低计算复杂度)去实现更高性价比的模型训练与推理。感兴趣的可以访问 GitHub 地址:OpenSeek@GitHub

    MemTensor

    随着 AI 技术的继续发展,预训练和后训练对于模型能力的增强的加速度是在下降的。那么,为了提升自然语言与模型的交互的效果,演讲者认为“记忆体”可能会成为增强大模型体验的关键组件。MemTensor团队则尝试通过将模型与“记忆”更加紧密的链接起来,从而增强模型的使用体验。

    关注的议题:

    最后

    GOSIM 大会大概有超过十个分论坛在并行分享,还有很多关于具身智能、Rust等相关的技术。

  • 最近

    ·

    最近参加了很多的线下的活动,包括了ACMUG、AWS 中国峰会、华为云HDC、IvorySQL & PostgreSQL生态大会,另外,还泡了一些杨梅酒、看了《长安的荔枝》,公司的产品“NineData”社区版发布了4.2.0。

    最近下线的活动很多,包括OceanBase、TiDB、各个云数据库厂商、各个数据库社区等,都在积极的组织一些社区活动,总的感受是,活动虽然很多,但开发者们对线下活动的热情是在减退的,而如果一场活动与AI关系不大,那么来现场的人一般是对这个技术的“真爱”。

    华为云的 HDC

    在上周末,受华为云数据库的朋友邀请,去参加华为云的 HDC 大会(开发者大会)。最近几年,和华为云的数据库合作比较多,也结识了很多华为云数据库团队的人。虽然数据库技术都是一样的,但每家公司都有着自己非常独特的环境与基因,有这自己不一样的风格。华为云数据库,感受着更多来自客户与一线的炮火,有着更接地气的拼劲。而整个公司因为在全球范围内的制裁压力,反而激发了更强的凝聚力。这次HDC大会上,华为云数据库发布了:GaussDB业务透明多写能力、“GaussDB Doer”一个面向华为云数据库的运维助手、TaurusDB for PostgreSQL

    此外,这次的HDC是在华为的松山湖园区,这是一个非常有特色的欧洲式建筑园区,随手拍了几张石雕,感受一下:

    前面的骑马的女神,大概是雅典娜
    拿着美杜莎之盾,大概是伯尔修斯
    经周陌认证,中间大概是波塞冬
    奥古斯都 屋大维

    ACMUG

    今年是 MySQL 30 年,这次成都的线下活动算是特别盛大的一次了,成都虽然有点远,但 MySQL 领域很多的有影响力的人去了。活动本身除了白天严肃的分享议题之外,下午、晚上大家随意闲聊各种八卦似乎要更有趣一些,这大概也是更多人参加的动力吧。

    亚马逊中国峰会

    这是因 NineData 赞助而去参加的活动,是以合作伙伴的身份参加的。Amazon的峰会在2015年的时候曾在上海参过一次,2018年还曾去过Vagas参加过一次re:Invent。Amazon 在全球云计算领域的地位依旧遥遥领先,但中国是一个特别的地方,确实很特别,无论是 Oracle 还是现在的 Amazon ,在全球大杀四方的时候,在中国却寸步难行,到底是谁的问题,一时难下结论,但这也确实给中国的厂商们留下一些时间和机会。

    云计算是现代应用非常底层的基础技术,而亚马逊作为一家美国的企业,要在中国开荒拓地,如果国际合作关系没有好转,未来大概是难有好转的。

    社区版发布4.2.0

    此外,这段时间,NineData 的社区版也发布了4.2.0,这是一个免费的(但不开源)数据库迁移同步工具,该免费版本中可以非常方便的帮助开发者完成诸如MySQL迁移、PostgreSQL迁移、Doris同步等工作。但如果是重要的生产环境或者需要长期运行的关键链路,则依旧建议考虑采购企业版。

    IvorySQL & PostgreSQL 生态大会

    这次大会主要由“瀚高”数据库团队在背后主办,是非常赞的活动,大会上有着关于 PostgreSQL 数据库方方面面的技术话题。这次参会,也认识了更多的 PostgreSQL 方向的开发者们。

    正如自己数年的感受一样:“PostgreSQL 在经历一场慢热的崛起”。从过去两三个月的两场收购(Neon、Crunchy Data)来看,在 AI 时代,PostgreSQL 依旧是在潮头的。

    杨梅酒

    最近几年,越来越体会到,杨梅是一种极为美味的水果了。杨梅大概在每年的6月初成熟,到了月底则已经逐渐下架,又因为其运输和保存都非常困难,也让这口美味,更显难得。江浙一带的杨梅种植技术大概是非常强的,这里的杨梅品种是非常独特的,甜中带着酸、酸中偷着甜,早上从台州一带的树上摘下,中午或晚上送到杭州,简单清洗一下,吃上十个八个,实为人间难得的美味。

    杨梅因为表面没有保护的表皮,所以其运输的难度比起荔枝要难数十倍。“杨贵妃”大概是没有尝过江浙一带的杨梅的,否则,则可能每年下江南一次。想运到长安或洛阳,不要说古代,即便是现在,都有一些困难的。

    喝酒这件事情,我大概是“人菜瘾大”的那类。在听说可以用杨梅泡酒后,从去年起就做了一些尝试。今年的杨梅酒已经按经验泡制、封存,约两个月后就可以品尝了。届时,如果感兴趣的,可以来我家“尝一尝”。

    长安的荔枝

    今年,一个多年未见的小学同学给我寄了一箱来自岭南一带的荔枝,放了半箱再公司,剩下的自己和家人吃了部分,上下楼的邻居也送了一些些。在此,代这些吃上荔枝的人一并感谢这位多年未见的同学。

    公众号久不更新,甚是心慌,记录如上,算是交代。

  • 随着 MySQL 对 JSON 类型的原生支持,操作 JSON 数据已变得非常高效与强大。在过去数年的版本中,MySQL 也在不断地增强 JSON 处理相关的功能。在 JSON 处理中需要非常频繁的使用“JSON Path” 语法,而这部分又是略微复杂的部分,本文将系统的介绍如何在 MySQL 中使用 JSON Path,包括语法规则、各种通配符用法、递归匹配等高级技巧,并通过丰富示例帮助开发者快速掌握。

    什么是 JSON Path?

    JSON Path 是一种表示法,用来描述如何在 JSON 文档中定位数据。类似于文件系统路径,JSON Path 指引着从 JSON 根节点出发,逐步深入结构内部。在 MySQL 中,几乎所有的 JSON相关的函数都会使用到,包括:JSON_EXTRACT()JSON_SET()JSON_REPLACE()JSON_REMOVE()JSON_CONTAINS()等。

    我们看到的场景的写法类似于:$.name$.colors[0]$.store**.price等。

    基础语法说明

    JSON Path的基础语法,遵循以下规则:

    • $:表示 JSON 文档的根节点。
    • .:用于访问对象中的属性。
    • ["key"]:另一种访问对象属性的方式,适合处理特殊字符的 key。
    • [index]:访问数组中的元素。
    • *:通配符,匹配所有子元素。
    • **:递归通配符,匹配所有嵌套层级的元素
    • [start to end]:数组范围选择

    JSON Path 基本示例

    示例表与示例数据

    创建带 JSON字段的表,并写入数据:

    CREATE TABLE t1 (
        id INT PRIMARY KEY AUTO_INCREMENT,
        data JSON
    );
    
    INSERT INTO t1 (data) VALUES
    ('{
      "name": "Alice",
      "age": 25,
      "email": "alice@example.com"
    }');

    提取对象字段

    这里使用基本的$.name引用根节点中属性为name的对象,示例如下:

    mysql> SELECT JSON_EXTRACT(data, '$.name') FROM t1;
    +------------------------------+
    | JSON_EXTRACT(data, '$.name') |
    +------------------------------+
    | "Alice"                      |
    +------------------------------+
    1 row in set (0.00 sec)

    也可以使用如下等价的写法data->'$.name'

    mysql> SELECT data->'$.name' FROM t1;
    +----------------+
    | data->'$.name' |
    +----------------+
    | "Alice"        |
    +----------------+

    访问数组元素

    初始化如下数据:

    -- truncate table t1;
    
    INSERT INTO t1 (data) VALUES
    ('{
      "colors": ["red", "green", "blue"]
    }');

    先访问colors属性,再查找该数组对象的第一个元素(注意:编号是0),故 JSON Path$.colors[0],示例如下:

    mysql> SELECT data->'$.colors[0]' AS first_color FROM t1;
    +-------------+
    | first_color |
    +-------------+
    | "red"       |
    +-------------+

    访问数组的范围

    除了像上述展示的,可以使用数值访问数组外,还可以使用0 to 1这样的语法表示一个范围,并访问数组中的多个元素:

    mysql> SELECT data->'$.colors[0 to 1]' AS first_color FROM t1;
    +------------------+
    | first_color      |
    +------------------+
    | ["red", "green"] |
    +------------------+
    
    mysql> SELECT data->'$.colors[1 to 1]' AS first_color FROM t1;
    +-------------+
    | ["green"]   |
    +-------------+
    
    mysql> SELECT data->'$.colors[1 to 2]' AS first_color FROM t1;
    +-------------------+
    | ["green", "blue"] |
    +-------------------+

    使用通配符

    准备示例数据

    为了展示相关的示例,这里先给出一个更为复杂的示例数据:

    CREATE TABLE t1 (
        id INT PRIMARY KEY AUTO_INCREMENT,
        data JSON
    );
    -- truncate table t1;
    
    INSERT INTO t1 (data) VALUES
    ('{
      "store": {
        "book": [
          {
            "category": "fiction",
            "title": "Harry Potter",
            "price": 29.99
          },
          {
            "category": "fiction",
            "title": "Lord of the Rings",
            "price": 49.99
          }
        ],
        "bicycle": {
          "color": "red",
          "price": 19.95
        }
      }
    }');

    使用通配符查询所有book

    则可以使用如下的搜索表达式:$.store.book[*]

    SELECT data->'$.store.book[*]' AS all_books 
    FROM t1;
    
    mysql> SELECT data->'$.store.book[*]' AS all_books
        -> FROM t1;
    +--------------------------------------------------------------+
    | all_books                                                    |
    +--------------------------------------------------------------+
    | [{"price": 29.99, "title"...}, {"price": 49.99, "title"...}] |
    +--------------------------------------------------------------+

    这里比较容易错误的写成:$.store.book.*$.store.book.[*]$.store.book*

    使用通配符递归查询

    列出所有书店中的书名

    依旧使用上述的数据,这里可以使用递归的通配符(**)查询结构中所有title属性的取值,则'$.store**.title'

    SELECT data->'$.store**.title' AS all_books 
    FROM t1;
    +---------------------------------------+
    | all_books                             |
    +---------------------------------------+
    | ["Harry Potter", "Lord of the Rings"] |
    +---------------------------------------+

    当然,也可以改成直接从“根”处开始递归查找,即$**.title

    mysql> SELECT data->'$**.title' AS all_books  FROM t1;
    +---------------------------------------+
    | all_books                             |
    +---------------------------------------+
    | ["Harry Potter", "Lord of the Rings"] |
    +---------------------------------------+

    类似的,我们还可以取出所有的价格:

    SELECT 
      data->'$.store**.price' AS book_prices 
    FROM t1;
    +-----------------------+
    | book_prices           |
    +-----------------------+
    | [29.99, 49.99, 19.95] |
    +-----------------------+

    小结

    熟悉 MySQL JSON Path Syntax 可以让开发者更加高效操作 JSON 数据。更多参考: