【论文阅读】Machine Learning, Linear Algebra, and More: Is SQL All You Need?

2024-05-13 21:52

本文主要是介绍【论文阅读】Machine Learning, Linear Algebra, and More: Is SQL All You Need?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 摘要
  • 一、介绍
  • 二、SQL算法原语
    • 2.1、Variables
    • 2.2、Functions
    • 2.3、Conditions
    • 2.4、Loops
    • 2.5、Errors
  • 三、案例研究
    • 3.1、对数据库友好的SQL映射
    • 3.2、性能结果
  • 四、结论以及未来工作


摘要

  尽管SQL在简单的分析查询中无处不在,但它很少用于更复杂的计算,如机器学习、线性代数和其他计算密集型算法。这些算法通常以过程方式编程,看起来与声明性SQL查询非常不同。然而,SQL实际上提供了执行各种计算的构造。在本文中,我们展示了如何将过程结构转换为SQL-启用复杂的SQL-only算法。在算法中使用SQL可以使计算更接近数据,只需要最小的用户权限,并增加软件的可移植性。生成的SQL算法的性能在很大程度上取决于底层DBMS和SQL代码。令人惊讶的是,我们发现像HyPer这样的查询引擎可以实现非常高的性能——在某些情况下甚至胜过像NumPy这样的最先进的线性代数包。

一、介绍

  理论上,任意计算都可以用SQL来表示。然而,这通常被认为是一种理论观察,而不是一种实际方法。在SQL中直接表示复杂算法的一个障碍是,算法通常是用过程语言表示的。SQL的声明性使得编写统计学习或优化算法的查询变得非常重要。

  目前,复杂的算法是在数据库系统之外实现的,使用用户定义函数(udf),或者依赖于系统特定的dbms内操作符。直接在SQL中表达算法有四个主要好处:

  • 近数据计算
      使用SQL算法,使得数据保留在数据库中,SQL查询引擎可以立即开始计算。并且只显示计算结果,而不显示底层数据,则可以确保更高的数据隐私。
  • 灵活性
      使用SQL可以自由定制修改,且只需要最小的用户权限就可以执行各种计算。
  • 高度抽象
      SQL算法的向量化、并行甚至分布式执行由底层DBMS自动完成
  • 可移植性
      如果SQL算法使用由多个DBMS供应商支持的通用SQL子集,那么该算法无需修改即可在其他DBMS上运行。

二、SQL算法原语

  在本节中,我们将过程语言的算法原语映射到SQL的声明性语法。为了演示这种转换,我们将展示Python和PostgreSQL的SQL方言中的代码片段。

2.1、Variables

  在SQL中,Variables可以表示为关系或关系中的值。这里的关系指的是一些数据结构,如标量、向量、矩阵、张量、集合、哈希表,甚至树和图。在SQL计算期间,可以使用WITH子句创建新变量。WITH子句允许命名子查询。然后可以在主查询中的几个位置引用这些命名的子查询。然而,与过程语言中的变量不同,SQL中使用with子句创建的变量是不可变的。要更新SQL变量,必须创建一个新变量。对于这类原语的python与SQL转换的例子如下:

在这里插入图片描述

2.2、Functions

  函数在大多数编程语言中都是必不可少的。SQL标准允许创建SQL函数,但并不是所有系统都支持。所以有一种替代方法是用WITH构造,从而允许将本地函数嵌入到SQL查询中。
在这里插入图片描述

2.3、Conditions

  标准SQL不提供分支结构,例如if-else来控制程序流。在SQL中,最接近if-else语句的结构是CASE语句。但是,CASE语句决定表达式的结果,因此类似于三元操作符而不是控制结构
  要在SQL中模拟条件控制流,UNION ALL构造是合适的。UNION ALL构造将两个或多个SELECT语句的结果组合在一起。通过只组合那些满足SELECT语句WHERE子句条件的结果,就可以模拟条件控制流(见清单3)。UNION ALL的唯一限制是各个SELECT语句中列的数量和列的数据类型必须匹配。
在这里插入图片描述

2.4、Loops

  在SQL中,循环有两种变体,它们是通过递归查询实现的,符合SQL标准[11]。大多数dbms都支持第一种变体,它是一个简单的循环,在子查询中没有递归引用(参见清单4),如下
在这里插入图片描述
  第二种变体包含子查询中的递归引用,据我们所知,它只在PostgreSQL、DuckDB和HyPer中得到完全支持,如下
在这里插入图片描述
  第二个循环变体允许在FROM子句的子查询中使用清单5中的递归工作表x。这些子查询也可以是递归的。如果对工作表的递归引用在FROM子句中出现超过一次,PostgreSQL将产生一个错误。可以通过在FROM子句中创建一个新变量并在以后的计算中引用它来避免这个错误(参见清单5中针对PostgreSQL的变通方法)我们大量利用子查询中的递归引用在SQL中实现各种算法。通过在子查询中支持递归引用,DBMS供应商可以在其产品中启用仅sql算法。

  递归查询的限制因素是缺乏拥有多个工作表的可能性。在递归中只允许有一个工作表。如果算法需要在每次迭代中更新多个变量,则必须立即将它们全部打包到工作表中。在迭代期间,这些变量必须从工作表中解包,然后再为下一次迭代重新打包。

2.5、Errors

  具有实用价值的SQL程序应该对错误的输入数据提供反馈。为了在SQL中实现输入验证,我们使用UNION ALL构造。在清单6中,计算了三种状态下概率分布的熵。概率的一个性质是它们大于等于零并且它们对所有状态的和是1。在创建错误关系时,在WHERE子句中检查这些前提条件。如果检测到错误输入,则Errors应该包含相应的错误消息。

在这里插入图片描述


三、案例研究

  这里使用基于梯度下降的逻辑回归作为案例研究,以证明以数据库友好风格编写的SQL算法是实用的。逻辑回归是一种流行的二元分类机器学习方法,它会导致以下凸优化问题:
在这里插入图片描述
  下面是一个用python写的基于梯度下降的逻辑回归
在这里插入图片描述

3.1、对数据库友好的SQL映射

  计算梯度是算法中最耗时的操作。如果性能很重要,那么用于计算梯度的SQL代码必须是数据库友好的。在这里,梯度计算主要由线性代数运算组成。SQL中的线性代数计算通常映射为一种格式,该格式显式存储向量或矩阵的每个值的索引。向量和矩阵的这种表示类似于用于稀疏线性代数的坐标格式(COO)。下面显示了如何在SQL中使用COO样式计算清单7中的梯度。
在这里插入图片描述
  在SQL中使用COO风格进行线性代数的一个优点是它的通用性,也就是说,SQL代码不依赖于矩阵中的列数。在使用COO风格时,默认情况下也支持稀疏线性代数。此外,正在进行积极的研究,以开发查询引擎,以减少类coo线性代数查询的执行时间[16]。然而,coo风格的SQL代码的性能可能不足,因为显式索引、糟糕的局部性和将数据转换为正确格式的昂贵转换会增加内存消耗。此外,SQL中co风格的线性代数严重依赖于连接。在清单8中,连接在WHERE子句中指定。

  SQL中coo风格线性代数的另一种方法是将关系本身视为向量或矩阵。关系的行和列对应于线性代数的行和列向量。向量和矩阵的这种表示类似于它们在密集线性代数中的表示。清单9显示了清单7中使用SQL中的密集线性代数样式的梯度计算。
在这里插入图片描述
  这里的梯度计算避免了连接,并且不需要为向量和矩阵提供显式索引。因此,我们称这种计算是数据库友好的。特性f1、f2和标签y存储在单个关系x中。在梯度计算过程中,特征和标签被传播以避免不必要的连接。例如,请查看在创建关系cse和v时如何选择特征f1和f2。例如在创建关系u时,当再次需要f1和f2时,这些“不必要的”选择避免了连接。

3.2、性能结果

  我们比较了NumPy、HyPer和PostgreSQL之间基于梯度下降的逻辑回归的性能。

  • NumPy是一个用于高性能科学计算的Python包。我们将NumPy链接到数学内核库(MKL)版本2020.0.2。英特尔的MKL库广泛使用矢量指令和多核处理。
  • HyPer是一个面向列的内存DBMS,在OLTP和OLAP工作负载下都能实现高性能[17]。我们使用Tableau公开的Hyper API版本0.0.13287。
  • PostgreSQL是一个广泛使用的、开源的、面向rowwororiented的DBMS。我们使用PostgreSQL 12.8版本。

  在我们的测量中,我们使用一台带有Intel i910980XE 18核处理器(36个超线程)的机器,运行Ubuntu 20.04.1 LTS,内存为128 GB。每个内核的基频为3.0 GHz,最大turbo频率为4.6 GHz,支持AVX-512矢量指令集。对于HyPer和PostgreSQL,我们测量了两种不同逻辑回归实现的性能。一种是基于coo风格的线性代数,另一种是数据库友好型的,使用无连接的密集风格进行线性代数(详细信息请参阅前一小节)。对于数据库测量,我们使用临时表。我们不使用数据库索引。在运行逻辑回归求解器时,我们以每秒迭代次数来报告性能。一次迭代计算梯度并更新前一次迭代的权重。我们验证所有实现计算相同的权重,从而获得相同的模型精度。

  下图显示了具有32个特征和100万个样本的数据集的基于梯度下降的逻辑回归的性能。虽然HyPer上的数据库友好实现实现了每秒100多次迭代,但PostgreSQL上的性能与它的COO实现没有什么不同。与HyPer相比,PostgreSQL的性能非常低,因为HyPer是一个使用查询编译的高效并行DBMS。因此,我们在进一步的测量中忽略了PostgreSQL。然而,令人惊讶的是,HyPer的速度几乎是NumPy的三倍。下面的测量探讨了HyPer优于NumPy的条件

在这里插入图片描述
  图2显示了性能取决于用于计算的线程数。当使用两个线程时,HyPer和NumPy的执行情况大致相同。当使用两个以上的线程时,HyPer上的数据库友好实现比NumPy快。随着可用内核数量的增加(线程数≤18),HyPer的性能会稳步提高。通过超线程的额外并行化,HyPer获得了更高的性能。与HyPer相比,NumPy中梯度计算的并行化很差。尽管MKL在并行化线性代数操作方面通常非常有效,但对于图2中包含32个特征的示例来说,它就失败了。

在这里插入图片描述
  在图3中,我们将特征的数量在4到128之间变化。我们把它留给实现来决定使用多少线程。NumPy利用数据集中所有18个核心和4个特征,但如图3所示,这种情况的效率相当低。图3显示,当数据集中少于128个特征时,HyPer是最快的替代方案。然而,HyPer和NumPy之间的性能差距随着数据集中特征数量的增加而缩小。在128个功能下,NumPy甚至比HyPer还要快一点
在这里插入图片描述

  图4显示了性能作为数据集中示例数量的函数。测量结果以对数标度表示。对于数据集中少于或等于105个示例,NumPy是最快的选择。NumPy将矩阵和向量连续地存储在内存中,因此当数据集适合缓存时,它将受益于良好的局部性。此外,由于权重更新依赖于先前计算的权重,因此对于小数据集,有效的并行化无法发挥作用。同样,为了进行基准测试,我们重复运行算法100次迭代。在HyPer中,这些时间包括缓存SQL查询的运行时。对于较小的数据量,查询的设置成本不会摊销。因此,对于小问题,NumPy要快得多。在HyPer中,测量中存在不规则性。对于数据集中的106个示例,HyPer每秒执行的迭代次数多于105个示例。这种不规律的原因是HyPer只通过一个线程执行少于或等于105个示例的所有查询。

在这里插入图片描述


四、结论以及未来工作

  纯sql算法不是一个理论噱头,但可以具有很高的实用价值。它们提供了诸如近数据计算、代码更改的灵活性、对底层DBMS体系结构的高度抽象以及可移植性等优点。我们展示了如何用SQL表示算法原语。通过使用这些原语,可以在SQL中实现计算密集型算法。在案例研究中,我们提供了数据库友好的SQL代码,它避免了线性代数操作的连接。事实证明在HyPer上的数据库友好型SQL实现甚至可以在更大的数据集上优于NumPy。

  算法中的循环通常包含对先前迭代数据的复杂计算。我们演示了如何在SQL中通过在WITH recursive的FROM子句中使用对工作表的递归引用来实现这种循环。像PostgreSQL、DuckDB或HyPer这样支持递归引用的dbms,已经可以使用SQL进行各种计算。扩展DBMS以支持子查询中的递归引用将是很简单的,我们希望本文能够促使DBMS开发人员实现这一特性。

  在未来的工作中,我们计划使用编译将命令式结构自动转换为SQL。编译器方法也可以将线性代数操作转换为SQL。为了使线性代数操作的转换尽可能高效,需要进一步探索SQL中无连接线性代数的局限性。深度学习似乎也是我们计划探索的一个有趣的用例。通过使用外部工具(如我们的矩阵演算[13-15])计算导数并将其转换为SQL,剩下要做的唯一事情就是在SQL中实现优化算法,这是可能的,正如我们在案例研究中所展示的那样。因此,我们相信SQL机器学习和其他形式的SQL计算密集分析非常有前途。

这篇关于【论文阅读】Machine Learning, Linear Algebra, and More: Is SQL All You Need?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/986927

相关文章

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份

AI hospital 论文Idea

一、Benchmarking Large Language Models on Communicative Medical Coaching: A Dataset and a Novel System论文地址含代码 大多数现有模型和工具主要迎合以患者为中心的服务。这项工作深入探讨了LLMs在提高医疗专业人员的沟通能力。目标是构建一个模拟实践环境,人类医生(即医学学习者)可以在其中与患者代理进行医学

[MySQL表的增删改查-进阶]

🌈个人主页:努力学编程’ ⛅个人推荐: c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 💻💻💻数据库约束 🔭🔭🔭约束类型 not null: 指示某列不能存储 NULL 值unique: 保证某列的每行必须有唯一的值default: 规定没有给列赋值时的默认值.primary key:

MySQL-CRUD入门1

文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们的MySQL服务安装好了之后, 会有一个配置文件, 也就