免费英语句子分析器 阿里p8和mysql哪个好

国学综合

免费英语句子分析器 阿里p8和mysql哪个好

极品老婆围观:℉更新时间:05-28 19:00

你现在阅读的是一篇关于免费英语句子分析器的文章,里面有丰富多彩的内容,还有给你准备阿里p8和mysql哪个好和免费英语句子分析器的精彩内容哦。

免费英语句子分析器 阿里p8和mysql哪个好

免费英语句子分析器 阿里p8和mysql哪个好

基本架构

MySQL 基本架构示意图如下:

MySQL 大体可以分为两部分:Server 层和存储引擎层(功能跟日常开发中的 Service 层和与 DAO 层有点像,可以对比理解)。

Server 层

主要有连接器(Connector)、查询缓存(Cache)、分析器(Parser)、优化器(Optimizer)和执行器(Executor)等,包括了 MySQL 的大部分核心功能以及所有内置函数(日期、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,例如存储过程、触发器、视图等。

存储引擎层

存储引擎(Storage Engine)层主要负责数据的存储和提取,它是直接和磁盘打交道的,以插件形式存在,例如 InnoDB、MyISAM、Memory 等多种存储引擎。

从 MySQL 5.5.5 开始,InnoDB 成为了默认的存储引擎。

Server 层

连接器

主要功能:跟客户端建立(TCP)连接、获取权限、维持和管理连接。

若用户认证通过,连接器会查询权限列表获取该用户的权限,之后该连接的权限判断都基于此(因此,一个用户建立连接后,即使被修改了权限也不会影响已存在连接的权限,只有重新建立连接后才生效)。

客户端建立连接示例(分别为失败和成功):

# 连接失败(密码错误)$ mysql -uroot -pEnter password:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
# 连接成功$ mysql -uroot -pEnter password:Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 7Server version: 5.7.19 MySQL Community Server (GPL)Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql>

进入 MySQL 后可以用如下命令查看连接状态:

# 查看连接状态mysql> show processlist;+----+------+-----------+------+---------+------+----------+------------------+| Id | User | Host | db | Command | Time | State | Info |+----+------+-----------+------+---------+------+----------+------------------+| 6 | root | localhost | NULL | Sleep | 81 | | NULL || 7 | root | localhost | NULL | Query | 0 | starting | show processlist |+----+------+-----------+------+---------+------+----------+------------------+2 rows in set (0.00 sec)

在 Command 列中,Sleep 表示该连接是空闲的。

连接成功后是有超时时间的,若太长时间没有操作会断开连接,由参数 wait_timeout 控制,默认为 8 小时,

查询缓存

主要功能:缓存查询结果。

连接建立之后,就可以进行查询了。

在一个查询语句中,会先到缓存中查询之前是否查询过该语句,若存在则直接返回对应的结果;否则继续执行后面的流程。

PS: 此处理流程可以类比我们在项目中使用 Redis 等作为缓存的操作,即先查缓存,再查 DB。

也可以通过使用 SQL_CACHE 显式指定使用查询缓存(这里的 id 并非主键),例如:

SELECT SQL_CACHE * FROM t1 WHERE id=10;

查询缓存的优缺点:

1. 优点:查询命中缓存时效率很高。

2. 缺点:缓存失效非常频繁,只要有对一个表的更新,该表所有的查询缓存都会被清空。

由于上述优缺点,可以发现缓存适用于静态表或更新较少的表,对于更新较频繁的表并不适用。值得一提的是,MySQL 8.0 版本已删除了查询缓存功能,可见该功能比较鸡肋。

分析器

主要功能:对 SQL 语句进行词法分析和语法分析。

1. 词法分析:分词操作,由于我们传递给 MySQL 的 SQL 语句实质上就是一个字符串,MySQL 需要将其拆分成一个个的分词(语法树)并进行识别,例如识别“SELECT”、“UPDATE”等关键字,将 t1 识别为一张表,将 id 识别为一列等。

2. 语法分析:拿到词法分析的结果,并根据语法规则判断 SQL 语句是否合法。若语法错误,则会收到如下错误提示:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ...

优化器

主要功能:优化 SQL 语句。

经过了分析器之后,MySQL 已经知道了我们提交的 SQL 语句是干嘛的。但为了提高执行效率,它并非完全按照我们的 SQL 语句执行,而要进行一系列优化。例如,当表中有多个索引时决定使用哪个索引;多表关联(JOIN)查询时决定表连接的顺序等等。

PS: 有点类似于 JVM 执行 Java 代码时的操作。即,JVM 并非完全按照代码的先后顺序来执行的,它会调整一些代码的执行顺序以提高效率,只是保证最终结果与代码顺序执行的效果一致。

执行器

主要功能:执行 SQL 语句。

MySQL 知道了我们要做什么,并且进行了优化,接下来就要开始执行了。执行之前,会判断你对该表是否有查询的权限,若有权限则继续执行;否则会返回如下错误(这里以 SELECT 操作为例,其他类似):

SELECT command denied to user 'user'@'localhost' for table 't1'

为什么到这一步才进行权限检查呢?

是因为有时候 SQL 语句要操作的表不只是 SQL 字面上的那些(例如触发器要在执行过程中才能确定),因此权限检查在这里进行。

存储引擎

以上述 SELECT 语句为例,执行步骤如下:

1. 调用 InnoDB 引擎接口取 t1 表的第一行,判断 id 是否为 10,若不是则跳过;否则将这一条记录存在结果集中;

2. 调用存储引擎接口读取“下一行”,判断逻辑同步骤 1,直至读取到表的最后一行;

3. 执行器将上述遍历过程中所有满足条件的记录作为结果集返回给客户端。

MySQL 查看所有存储引擎:

mysql> show engines;+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+| Engine | Support | Comment | Transactions | XA | Savepoints |+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES || MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO || MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO || BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO || MyISAM | YES | MyISAM storage engine | NO | NO | NO || CSV | YES | CSV storage engine | NO | NO | NO || ARCHIVE | YES | Archive storage engine | NO | NO | NO || PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO || FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+9 rows in set (0.00 sec)

其中 Support 表示该引擎是否可用(DEFAULT 表示默认值);Comment 是描述信息;Transactions 表示是否支持事务;XA 表示是否支持分布式事务;Savepoints 表示是否支持回滚。

其中最为常用的就是 InnoDB 引擎,而且它也是默认的。其他常见的还有 MyISAM 和 Memory 引擎,这三种引擎简单对比如下:

MyISAMInnoDBMemory存储限制256TB64TB有事务???索引???锁表锁行级锁表锁外键???

小结

MySQL 的整体架构主要分为两部分:Server 层和存储引擎层。

Server 主要有连接器、查询缓存、分析器、优化器和执行器等,包括了 MySQL 的大部分核心功能以及所有内置函数,所有跨存储引擎的功能都在这一层实现,例如存储过程、触发器、视图等。

存储引擎层:负责数据的存储和提取,以插件形式存在,例如 InnoDB (MySQL 5.5.5 以后默认的存储引擎)、MyISAM、Memory 等多种存储引擎。

PS: 发现一个现象,许多东西在学的时候觉得不难,但是如果自己不去做笔记的话就很容易忘记。因此就需要用自己的语言去表达出来,这样更能促进思考,也能进一步“内化”到自己的知识体系中。

索引

简单来说,索引的出现是为了提高查询效率,就像书的目录一样。MySQL 的索引是在「存储引擎」层实现的,因此没有统一的标准,同一种类型的索引,在不同存储引擎之间实现可能也不同。本文主要分析 InnoDB 存储引擎的索引结构。

索引模型

索引模型就是索引的实现形式(也可以理解为索引的数据结构),常见的索引模型有下面三种:

1. 哈希表(散列表)

键值对形式(类似 Java 中的 HashMap)

优点:新增速度快;

缺点:无序,区间查询速度很慢(全表扫描)。

适用场景:只有等值查询的情况(例如 Memcached 等一些 NoSQL 引擎)。

2. 有序数组

优点:等值查询和范围查询速度都很快。

缺点:更新成本太高(插入的记录在中间时,需要移动后面的所有记录,可类比在数组中间位置插入元素的操作)。

适用场景:静态存储引擎(比如不再修改的历史数据)。

3. 搜索树(N 叉树)

优点:读写快,适配磁盘的访问模式。

B+ 树就是其中的一种,也是 InnoDB 存储引擎的索引模型。

InnoDB 记录的存储结构

数据页

在 InnoDB 引擎中,会将数据划分为若干个「页」,「页」是磁盘和内存之间交互的基本单位,页的大小一般为 16KB。即:一般情况下,一次最少从磁盘中读取 16KB 的数据到内存中,一次至少把内存中 16KB 的数据刷新到磁盘中。

向一个数据页中插入记录的过程如图所示:

数据页中分为几个部分,其中 User Records 部分为存储记录的空间(其他部分存储数据页的其他信息,这里暂不详述),插入过程大致如下:

1. 未插入记录时,User Records 部分不存在;

2. 当插入记录时,会从 Free Space 部分划分出空间存储记录;

3. 当 Free Space 空间用完时,也就是该数据页的空间用完了,需要分配新的数据页存储(页分裂)。

记录的结构

在 InnoDB 引擎中,一条记录的存储结构如图所示:

PS: 其中橙色部分 (c1, c2, c3) 是表中的列,且 c1 为主键,下图亦是如此。

也就是说,数据页中记录的数据,除了一条记录本身,还有变长字段列表、NULL 值列表、记录头信息等其他信息,这样才是在数据页中的一条完整记录。

数据页中多条记录之间的关系示意图:

即,每个页中保存了许多条记录,并且每条记录指向下一条记录(根据主键顺序,类似单链表结构)。此外还记录了该页中的最小和最大记录(也是根据主键顺序)。

不仅如此,这些记录还会几条(1~8)分为一个组,并且把组内最大的主键值提取到一个槽(slot)中,用来实现快速(二分)查找,示意图如下:

页内查找记录

以上面的数据页为例,若要查找主键值为 5 的记录,过程如下(二分查找):

1. 计算中间槽的位置:(0+4)/2=2,因此查找槽 2,而它对应记录的主键为 8,5<8,重新计算;

2. 重新计算,(0+2)/2=1,查找槽 1,对应记录的主键值为 4,5>4,因此查找的记录在槽 2 中;

3. 遍历槽 2 对应的分组,查找主键为 5 的记录。

因此在一个数据页中查找指定主键值的记录过程大致分为两步:

1. 通过二分查找确定记录所在的槽;

2. 遍历该槽所在组中的各个记录(通过记录的 next_record)。

由于槽内数据很少(不超过 8 条),因此遍历的成本较低。

聚簇索引&二级索引

根据叶子节点的内容,索引类型可分为「聚簇索引」(Clustered Index)和「二级索引」(Secondary Index)。

1. 聚簇索引

在 InnoDB 存储引擎中,聚簇索引也称为「主键索引」,表都是根据主键顺序组织存放的,这种存储方式的表称为索引组织(Index Organized Table)表(索引即数据,数据即索引)。一张表只能有一个主键索引。

聚簇索引的示意图如下(该结构就是一棵 B+ 树):

图中结构分为三层,其中上面的两层(即非叶子节点,页 33、页 30 和页 32)为索引层,保存的是索引信息;第三层(叶子节点)为数据层。在主键索引中,叶子节点保存的是完整的记录(以数据页为单位)。

PS: 存储节点的空间可能是不连续的,但是,同一层的节点是有前后顺序的,它们之间以「双向链表」的形式连接。

在索引树中查找一条记录的大致过程如下(仍以查找主键值为 5 的记录为例):

1. 先查找根节点,即页 33,页 30 中的主键范围是 [1, 320),而页 32 中主键大于等于 320,因此定位到 页 30;

2. 再查找页 30,同样的方法定位到页 28;

3. 根据上面「页内查找记录」的方式在页 28 中查找。

2. 二级索引

InnoDB 中,二级索引的叶子节点存储的是主键的值。二级索引也称为「非聚簇索引」、「非主键索引」。一张表可以有多个二级索引。其中,以单列作为二级索引的又称「单列索引」,以多列作为索引的又称「联合索引」或者「组合索引」。

二级索引的示意图如下:

该结构与聚簇索引类似,也是一棵 B+ 树。

与聚簇索引的不同之处主要在于第三层,也就是叶子节点,在二级索引中,叶子节点保存的是主键的值。

二级索引中的查找过程与聚簇索引中查找类似。

不同的是,由于二级索引保存的是索引列和主键列,若查找的数据包含索引和主键之外的内容,则需要先找出主键值,然后再根据主键的值到聚簇索引中查找完整记录,该过程称为「回表」。

值得注意的是,上述查找都是在有索引的情况下进行的,如果没有索引呢?则会进行全表扫描,这样当数据量较大时,效率会非常低。这也是索引出现的主要原因。

区别与联系(InnoDB 存储引擎)

1. 聚簇索引和二级索引都需要占用磁盘空间,每一个索引都对应一棵索引树;

2. 二者都是 B+ 树结构,数据都存储在叶子节点(非叶子节点不保存数据);

3. 聚簇索引的叶子节点保存的是完整记录,二级索引保存的是主键的值;

4. 在一张表中,聚簇索引只能有一个,二级索引可以有多个(即多个索引树)。

根据这几点比较也可以发现,索引虽然可以提高查找效率,但也有缺点。如果有多个索引,当修改数据时索引也要同步进行更新,这样会降低操作的效率;而且索引也会占用磁盘空间。因此,索引并非越多越好。

InnoDB 引擎主键选择

在 InnoDB 中,每张表都有个主键(Primary Key),如果在建表时没有显式地定义主键,则 InnoDB 引擎会按照如下方式选择或创建主键:

1. 首先判断表中是否有非空的唯一索引(Unique NOT NULL),若有,则该列即为主键(当表中有多个非空唯一索引时,InnoDB 存储引擎将选择建表时第一个定义的非空唯一索引为主键);

2. 若不符合上述条件,InnoDB 存储引擎自动创建一个 6 字节大小的隐藏列(row_id)作为主键。

因此,建表时最好显式指定主键。

索引优缺点

主要优缺点如下(可通过上述存储结构分析理解):

优点

1. 可以提高数据检索效率,降低数据库 IO 成本;

2. 对记录进行排序,降低 CPU 消耗(被索引的列会自动进行排序),可以提高排序和分组查询的效率。

缺点

1. 索引会占用磁盘空间;

2. 降低更新效率(更新操作会同步更新索引)。

索引使用场景

需要创建索引的场景

1. 主键自动建立唯一索引;

2. 频繁作为查询条件的字段应该创建索引;

3. 多表关联查询中,关联字段应该创建索引(ON 两边都要创建);

4. 查询中排序的字段,应该创建索引;

5. 统计或者分组。

不需要使用索引的场景

1. 表记录太少;

2. 频繁更新;

3. 查询字段使用频率不高。

PS: 这里只是概括了一些常见的优缺点和使用场景,可以根据前面对索引的结构和特点的分析对比理解。

小结

简单来说,索引可以理解为书的目录。

索引的主要作用是为了提高查找效率;但索引也有缺点,并非越多越好,需要根据实际情况决定如何创建合适的索引。

免费英语句子分析器(深入理解SQL原理)

本篇文章将通过一条 SQL 的执行过程来介绍 MySQL 的基础架构。

首先有一个 user_info 表,表里有一个 id 字段,执行下面这条查询语句:

select * from user_info where id = 1;

返回结果为:

+----+----------+----------+--------+------+---------------------+---------------------+| id | username | password | openid | role | create_time | update_time |+----+----------+----------+--------+------+---------------------+---------------------+| 1 | 武培轩 | 123 | 1 | 1 | 2023-08-29 00:29:08 | 2023-08-29 00:29:08 |+----+----------+----------+--------+------+---------------------+---------------------+

下面给出 MySQL 的基本架构示意图,可以看出 SQL 语句在 MySQL 的各个模块中的执行过程。

MySQL 基本架构

大体上,MySQL 分为 Server 层和存储引擎层两部分。

Server 层包括连接器、查询缓存、分析器、执行器等,以及所有的内置函数(如日期、时间、数学和加密函数等)和跨存储引擎的功能(如存储过程、触发器、视图)。

存储引擎层负责数据的存储和提取,支持 InnoDB、MyISAM、Memory 等多个存储引擎。MySQL 5.5.5 版本后默认存储存储引擎是 InnoDB。

1.连接器(Connector)

在查询 SQL 语句前,肯定要先建立与 MySQL 的连接,这就是由连接器来完成的。连接器负责跟客户端建立连接、获取权限、维持和管理连接。连接命令为:

mysql -h$ip -P$port -u$user -p

输入密码,验证通过后,连接器会到权限表里面查出你拥有的权限,之后这个连接里面的权限判断逻辑,都将依赖于此时读到的权限,一个用户成功建立连接后,即使管理员对这个用户的权限做了修改,也不会影响已经存在连接的权限,修改完后,只有再新建的连接才会使用新的权限设置。

连接完成后,如果你没有后续的动作,这个连接就处于空闲状态,你可以在 show processlist 命令中看到它。结果如下:

+----+------+----------------+------------------+---------+------+----------+------------------+| Id | User | Host | db | Command | Time | State | Info |+----+------+----------------+------------------+---------+------+----------+------------------+| 3 | root | localhost:2790 | NULL | Sleep | 5878 | | NULL || 4 | root | localhost:2791 | springcloud_sell | Sleep | 5838 | | NULL || 7 | root | localhost:2900 | springcloud_sell | Sleep | 5838 | | NULL || 10 | root | localhost:3627 | springcloud_sell | Query | 0 | starting | show processlist |+----+------+----------------+------------------+---------+------+----------+------------------+

客户端如果太长时间没动静,连接器就会自动将它断开;这个时间是由参数 wait_timeout 控制的,默认值是8小时。如果在连接被断开之后,客户端再次发送请求的话,就会收到一个错误提醒:Lost connection to MySQL server during query。

长连接和短连接

建立连接的过程通常是比较复杂的,建议在使用中要尽量减少建立连接的动作,尽量使用长连接。但是全部使用长连接后,有时候 MySQL 占用内存涨得特别快,这是因为 MySQL 在执行过程中临时使用的内存是管理在连接对象里面的。这些资源会在连接断

开的时候才释放。所以如果长连接累积下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现象看就是 MySQL 异常重启了。

怎么解决这个问题呢?可以考虑以下两种方案:

  1. 定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。
  2. MySQL 5.7 以上版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。

2.查询缓存(Query Cache)

在建立连接后,就开始执行 select 语句了,执行前首先会查询缓存。

MySQL 拿到查询请求后,会先查询缓存,看是不是执行过这条语句。执行过的语句及其结果会以 key-value 对的形式保存在一定的内存区域中。key 是查询的语句,value 是查询的结果。如果你的查询能够直接在这个缓存中找到 key,那么这个

value 就会被直接返回给客户端。

如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,会提升效率。

但是查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。对于更新压力大的数据库来说,查询缓存的命中率会非常低。如果业务中需要有一张静态表,很长时间才会更新一次。比如,一个系统配置表,那这张表上的查询才适合使用查询缓存。MySQL 提供了这种按需使用的方式。可以将参数 query_cache_type 设置成 DEMAND,对于默认的 SQL 语句都将不使用查询缓存。而对于你确定要使用查询缓存的语句,可以用 SQL_CACHE 显式指定,如下:

mysql> select SQL_CACHE * from user_info where id = 1;

MySQL 8.0 版本将查询缓存的功能删除了。

3.分析器(Analyzer)

如果查询缓存未命中,就要开始执行语句了。首先,MySQL 需要对 SQL 语句进行解析。

分析器先会做词法分析。SQL 语句是由多个字符串和空格组成的,MySQL 需要识别出里面的字符串分别是什么,代表什么。MySQL 从你输入的 select 这个关键字识别出来,这是查询语句。它也要把字符串 user_info 识别成表名,把字符串 id 识别成列名。之后就要做语法分析。根据词法分析的结果,语法分析器会根据语法规则,判断输入的 SQL 语句是否满足 MySQL 语法。

如果你 SQL 语句不对,就会收到 You have an error in your SQL syntax 的错误提醒,比如下面这个语句 from 写成了 form。

mysql> select * form user_info where id = 1;1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'form user_info where id = 1' at line 1

一般语法错误会提示第一个出现错误的位置,所以要关注的是紧接 use near 的内容。

4.优化器(Optimizer)

经过分析器的词法分析和语法分析后,还要经过优化器的处理。

优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。比如你执行下面这样的语句,这个语句是执行两个表的 join:

mysql> SELECT * FROM order_master JOIN order_detail USING (order_id) WHERE order_master.pay_status = 0 AND order_detail.detail_id = 1558963262141624521;

既可以先从表 order_master 里面取出 pay_status = 0 的记录的 order_id 值,再根据 order_id 值关联到表 order_detail,再判断 order_detail 里面 detail_id 的值是否等于 1558963262141624521。

也可以先从表 order_detail 里面取出 detail_id = 1558963262141624521 的记录的 order_id 值,再根据 order_id 值关联到 order_master,再判断 order_master 里面 pay_status 的值是否等于 0。

这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。优化器阶段完成后,这个语句的执行方案就确定下来了,然后进入执行器阶段。

5.执行器(Actuator)

MySQL 通过分析器知道了要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。

开始执行的时候,要先判断一下你对这个表 user_info 有没有执行查询的权限,如果没有,就会返回没有权限的错误,如下所示 (如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证。查询也会在优化器之前调用 precheck 验证权限)。

mysql> select * from user_info where id = 1;ERROR 1142 (42000): SELECT command denied to user 'wupx'@'localhost' for table 'user_info'

如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。比如我们这个例子中的表 user_info 中,id 字段没有索引,那么执行器的执行流程是这样的:

  1. 调用 InnoDB 引擎接口取这个表的第一行,判断 id 值是不是 1,如果不是则跳过,如果是则将这行存在结果集中;
  2. 调用引擎接口取下一行,重复相同的判断逻辑,直到取到这个表的最后一行。
  3. 执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。

对于有索引的表,第一次调用的是取满足条件的第一行这个接口,之后循环取满足条件的下一行这个接口。

数据库的慢查询日志中有 rows_examined 字段,表示这个语句执行过程中扫描了多少行。这个值就是在执行器每次调用引擎获取数据行的时候累加的。在有些场景下,执行器调用一次,在引擎内部则扫描了多行,因此引擎扫描行数跟 rows_examined 并不是完全相同的。

总结

主要通过对一个 SQL 语句完整执行过程进行讲解,介绍 MySQL 的逻辑架构,MySQL 主要包括连接器、查询缓存、分析器、优化器、执行器这几个模块。

点关注,不迷路!

免费英语句子分析器(知其然更要知其所以然)

SQLite是一个非常受欢迎的数据库,在数据库排行榜中已经进入前十的行列。这主要是因为该数据库非常小巧,而且可以支持Linux、Windows、iOS和Andriod的主流的操作系统。

SQLite非常简单,是一个进程内的动态库数据库。其最大的特点是可以支持不同的语言来使用,比如C、C++、Java等等。同时,SQLite还是一个开源的数据库,也就是开发者可以根据自己的需求来修改数据的功能特性。

SQLite虽然非常小巧,但功能却非常丰富,正所谓“麻雀虽小,五脏俱全”。SQLite不仅具备基本的SQL特性,还具备索引、触发器、视图和事务等特性。

SQLite的主要API

SQLite提供两种访问接口,一种是通过sqlite命令行工具,另外一种是通过动态库,也就是API函数。在学习SQLite架构之前,我们有必要对其API进行一个简要的介绍。其实SQLite的API很简单,主要包括三个,分别是sqlite3_open、sqlite3_exec和sqlite3_close三个函数。其中sqlite3_exec则是用于执行SQL语句的函数。

也就是说sqlite3_exec是SQLite功能的关键入口,我们后面分析代码也应该以此函数作为突破点。其它函数相对简单,也没那么重要。

SQLite整体架构

首先我们从整体架构上介绍一下SQLIte。其架构如图所示,包括接口层、SQL命令处理器和存储后端等。

最为核心的不是就是SQLite内核了。其中包括接口层、SQL命令处理器和虚拟机三部分。SQL命令处理器负责对用户的SQL进行预处理,最终生成适用于虚拟机执行的代码。

其下是后端部分,后端部分相当于存储引擎。下面我们简要的介绍一下每个模块的功能。

接口

SQLIte库的使用通过函数调用实现。为了避免与其它库出现冲突,SQLite的函数都以sqlite3作为前缀。接口部分的实现在文件main.c,legacy.c和vdbeapi.c中。其中main.c中包含其主要的接口,包括sqlite3_open、sqlite3_config和sqlite3_close等等。SQLite中最终的函数不在main.c中,而是在legacy.c中,该文件中只包含这一个接口的实现。

词法分析器

词法分析器对SQL语句字符串进行解析,最终生成单词(token)序列。并且将生成的单词序列传给解析器进行下一步的动作。该功能的具体实现在文件tokenize.c中,核心入口函数为sqlite3RunParser。

解析器

SQLite的解析器基于Lemon实现,它实现将SQL语句字符串解析成语法树。Lemon是一个与YACC/BISON类似的词法分析库。该库的源代码在tool目录中。

代码生成器

代码生成器用于生成与SQL语句对应,可以在虚拟机执行的代码。代码生成器实现比较复杂,包含的文件有:build.c, delete.c, attach.c, expr.c, insert.c, pragma.c, select.c, auth.c等等。通过文件名可以看出,这里很多文件其实分别对应着一个SQL语句,比如delete,insert和select等。

虚拟机

SQL的具体执行在一个称为虚拟机的组件中进行的,这个在前面架构图中已经有所展示。虚拟机执行的代码有前面代码生成器产生。虚拟机的实现在文件vdbe.h和vdbe.c中。

B-树

SQLite的数据通过B树进行组织管理。每个表或者索引都有一个对应的B树。所有的B树存储在一个数据库文件中。B树的具体实现在btree.c和btree.h文件中。

页缓存

SQLite的文件被划分为等份大小,B树也是以该大小为粒度来对数据进行管理。页缓存是该粒度对应的内存内容,通过该内存实现对数据块的读写等访问。页缓存相关的实现在pager.c和pcache.c等文件中。

操作系统接口

SQLite是一个跨平台的数据库,其存储数据需要兼容Windows和Linux的文件系统API。为了方便,SQLite实现了一个抽象层。这样对于SQLite业务逻辑来说,只需要调用该抽象层的接口即可,而不用关心操作系统。

基础库

包含一个被各个模块都可能使用到的基础库,比如内存分配,字符串处理等。

SQLite文件格式

前文我们简要的介绍了一下SQLite的软件架构以及每个组件的基本功能。接下来我们介绍一下数据库文件的相关功能。

在SQLite中一个文件承载着一个数据库实例,这个文件称为主库文件(main database file)。除了主库文件外,还可能有一些其它文件,比如用于事务的日志文件等。本文主要集中介绍主库文件,其它文件后续介绍。

数据库文件由多个页构成,每个页的大小在512到65536字节之间,且大小必须是2的幂。页通过编号进行标记,起始值为1,最大编号为2的31次幂-2。页的默认大小是4KB,本文以默认大小为例进行介绍。

在数据库中的每个页都有一个特定的用途,这些用途包括:

数据库文件的第一个页是比较特殊的,它包含整个数据库文件的描述信息,这里称为数据库头信息。

数据库头

数据库头包含100个字节的内容,其中每一个成员的偏移,大小和功能如下图所示。

我们可以创建一个数据库实例,然后对照文件内容与数据库头的格式进行理解。比如数据库头的第一个成员为一个魔数,用于标识该文件为SQLite数据库文件及版本。在下图中可以找到该信息,可以看出两者完全匹配(SQLite format 3)。

除了上述数据库头的格式外,每个不同的页都有不同的布局。限于篇幅,本文暂时不过多介绍,后面结合实例专门写一篇文章介绍各种不同的页的布局。

参考内容

[1] https://www.cnblogs.com/YSPXIZHEN/p/5792459.html

[2] https://sqlite.org/index.html

[3] https://www.runoob.com/sqlite/sqlite-c-cpp.html

[4] https://sqlite.org/fileformat.html

免费英语句子分析器(机器翻译的结构不变测试)

摘要

近年来,机器翻译软件越来越多地融入到我们的日常生活中。人们经常在各种应用程序中使用机器翻译。然而,为现代机器翻译提供动力的神经机器翻译(NMT)模型的复杂性和难处理性使得这些系统的鲁棒性难以评估,更难以保证。机器翻译系统返回低质量的结果会导致误解、医疗误诊、人身安全威胁或政治冲突。尽管其明显的重要性,确认机器翻译系统的鲁棒性是非常困难的,因此,还没有充分的探索。

为了解决这个问题,我们引入了结构不变测试(SIT),一种新的蜕变测试方法来验证机器翻译软件。我们的主要观点是“相似”的原句翻译结果应该典型地表现出相似的句子结构。具体来说,SIT(1)通过将给定句子中的一个词替换为语义相似的词来生成相似的源句;(2)通过语法解析树(通过选区或依赖解析获得)表示句子结构;(3)报告结构数量差异超过某个阈值的句子对。为了评估 SIT,我们使用它来测试谷歌翻译和微软必应翻译,输入 200 个源句,导致 64 个和 70 个 bug,分别是 69.5%和 70%的 top-1 准确率。翻译错误多种多样,包括翻译不足、过度翻译、修改错误、词/短语误译、逻辑不清等。

1 介绍

机器翻译软件在过去的十年中得到了快速的发展:现在用户在各种应用中都依赖机器翻译,比如在国外留学时签订租赁协议、向外国医生描述症状,以及用外语阅读政治新闻。2023 年,谷歌翻译作为使用最广泛的在线翻译服务,吸引了超过 5 亿用户,每天翻译超过 1000 亿字。除此之外,机器翻译服务也嵌入到各种应用软件,如 Facebook 和 Twitter。

机器翻译的发展在很大程度上可以归因于神经机器翻译(NMT)模型,它已经成为许多机器翻译系统的核心组件。根据谷歌和微软的研究报告,就精确度而言,最先进的 NMT 模型正在接近人类水平,即 BLEU。这些最近的突破使得用户开始在日常生活中依赖机器翻译软件(如谷歌翻译和微软必应翻译)。

然而,NMT 模型并不像许多人认为的那样可靠。近年来,以神经网络为核心的软件系统中出现了次优和错误输出的现象。典型的例子包括自动驾驶汽车、情绪分析工具和语音识别服务。这些最近的研究成果表明,神经网络可以很容易地在给定特定的输入(例如,对抗样本)的情况下返回较差的结果(例如,错误的类标签)。NMT 模型也不例外,他们可能会被对抗样本或自然噪音(例如,输入句子中的拼写错误)所愚弄。这些较差的结果(即,次优或错误的翻译)会导致误解、尴尬、经济损失、医疗误诊、对个人安全的威胁或政治冲突。因此,保证机器翻译软件的鲁棒性是一项重要的工作。

然而,测试机器翻译软件是极具挑战性的。首先,机器翻译软件不同于用源代码编码的传统软件的逻辑,它基于复杂的神经网络,有数百万个参数。因此,传统软件(大多基于代码)的测试技术是无效的。其次,测试人工智能(Al)软件的最新研究关注于具有更简单输出格式的任务——例如,测试图像分类器,它输出给定图像的类标签。然而,作为最困难的自然语言处理(NLP)任务之一,机器翻译系统(即翻译的句子)的输出要复杂得多。因为它们不是用来处理这种复杂输出的,所以当应用到 NMT 模型时,典型的 Al 测试方法几乎只能找到“非法”输入,比如有语法错误或明显拼写错误的句子,而这些句子不太可能作为输入给出。然而,这些错误并不是在实践中出现的问题;微信是一个月活跃用户超过 10 亿的社交应用,据报道,其嵌入的 NMT 模型即使在句法正确的情况下也会返回较差的结果。由于很难建立一个有效的、自动化的方法来评估翻译的正确性,目前的机器翻译软件测试方法有很多缺点。

试图解决上述问题的方法仍然有其自身的缺陷——即,无法检测语法错误和缺乏真实世界的测试用例。目前机器翻译软件的测试程序一般包括三个步骤:(1)收集双语句子配对和将它们分为训练数据、验证数据和测试数据;(2)计算训练好的 NMT 模型对测试数据的翻译质量分数(如 BLEU 和 ROUGE);(3)比较分数与预定义的阈值,以确定测试用例是否通过。然而,基于像 BLEU 这样的阈值分数的测试,很容易忽略语法错误。BLEU 是对目标和参照的 n 个字母重叠程度的衡量。另外,在计算翻译质量分数(如 BLEU)时,需要输入双语句子对,事先手工构建。要使用训练集之外的真实用户输入进行测试,需要大量的手工工作来进行基础真值翻译。因此,迫切需要一种能够自动检测机器翻译软件中的错误的有效的测试方法。

为了解决上述问题,本文引入了结构不变测试(SIT),这是一种新颖的、广泛适用的机器翻译软件验证方法。关键的洞察力是类似的来源句子——一个单词不同的句子通常会有相似的句子结构的翻译结果。例如,图 1 展示了三个相似的英语源句和汉语目标句。前两个翻译是正确的,而第三个则不正确。我们可以看到,汉语中第三句的结构与其他两句有明显的不同。对于每一个源句,SIT(1)通过 NLP 技术(即 BERT[19)修改源句中的一个单词,生成一个类似的句子列表;(2)将所有的句子输入待测软件,获取译文;(3)使用专门的数据结构(即选区解析树和依赖解析树)来表示每个翻译句子的语法结构;(4)比较翻译后的句子结构。如果译文的原句和任何一个修改后的句子在结构上存在较大的差异,将修改后的句子和原句一起报告为潜在的错误。

图 1.类似源句和谷歌翻译结果的例子

他们使用 SIT 测试谷歌翻译和微软必应翻译,从网上抓取 200 个源句作为输入。SIT 成功地发现谷歌翻译中 64 个 bug 和微软必应翻译中 70 个 bug(分别为 69.5%和 70%的 top-1 准确率)。报告的错误多种多样,包括翻译不足、过度翻译、不正确的修改、单词/短语错译和逻辑不清楚,这些都不能被广泛使用的度量指标 BLEU 和 ROUGE 检测到。

本文的主要贡献如下:它介绍了结构不变测试(SIT),一种新颖的、广泛适用的机器翻译软件验证方法;它描述了一个 SIT 的实际实现,通过采用 BERT 来生成相似的句子,并利用语法分析器来表示句子结构;仅用从网上抓取的 200 个源句就对 SIT 进行了评估,成功地找到了谷歌翻译中的 64 个 bug 和微软必应翻译中的 70 个 bug,且准确率很高;它讨论了由 SIT 发现的各种错误类别,其中没有一个可以被最先进的度量标准发现。

2 方法和实现

本节将介绍结构不变测试(SIT)并描述其实现。SIT 的输入是一个未标记的单语句子列表,而输出是一个可疑问题列表。对于每个原始的句子,SIT 报告 0(即,没有发现错误的句子)或 1 个问题(即,至少发现了一个错误的句子)。每个问题包含:(1)原句及其译文;(2)top-k 生成的原句及其译文。原句对被报道的原因如下:(1)观察原句是如何被修改的可能可以帮助用户理解翻译系统出错的原因;(2)实际上,错误可能在于原句的翻译。图 2 说明了 SIT 的概述。在这个图中,为了简单和清晰,使用一个源句作为输入。SIT 的关键洞见是相似的源句往往具有相似的句法结构的目标句。基于这一见解,SIT 实施了以下四个步骤:

(1)产生类似的句子。对于每个源句,通过修改句子中的一个单词来生成一个类似句子的列表。

(2)收集目标句子。将原始的和生成的相似的句子输入被测机器翻译系统,并收集它们的目标句子。

(3)表示目标句子结构。所有的目标句都被编码为专门用于自然语言处理的数据结构。

(4)检测翻译错误。将译出的修饰句的结构与句子的结构进行了比较,如果结构之间有很大的差异,SIT 报告一个潜在的错误。

图 2.SIT 的概述

2.1 产生类似的句子

为了测试结构的不变性,必须比较两个句法结构相同但至少有一个标记不同的句子。研究发现,给定一个输入句子,在一定的约束条件下,一次改变句子中的一个词,可以有效地生成一组结构相同、语义相似的句子。

显式地,他们采用的方法是修改输入句子中的单个标记,用另一个具有相同词性的标记(POS)替换它,从而生成一个备用句子。对句子中的每一个候选标记都这样做:为了简单和避免语法上奇怪或错误的句子,他们只使用名词和形容词作为候选标记。

他们需要一个模型来考虑周围的单词,并提出一组替换,当插入这些替换时,就可以创建现实的句子。这样做的模型就是 MLM。MLM 的输入是带有单个标记屏蔽的一段文本(例如,从句子中删除并替换为一个特殊的指示符标记)。然后,模型的工作就是在给定的上下文中预测那个位置的标记。这种方法迫使模型了解不同令牌之间的依赖关系。由于单个单词可以适应许多不同的上下文,因此在某种意义上,该模型允许单个标记具有多个表示形式。继而,得到一组依赖于上下文的替换标记。虽然预测的令牌不能保证具有与原始令牌相同的含义,但如果 MLM 是经过良好训练的,则很可能带有新预测标记的句子在语法上是正确的,而且有意义。

一个句子生成过程的例子如图 3 所示。对于实现,他们使用 BERT,是谷歌最近提出的一种最新的语言表示模型。即用 BERT 模型提供预先训练好的语言表示,可以通过添加额外的轻量级 softmax 分类调整层来创建模型广泛的语言学习任务。

图 3.类似句子的生成过程

2.2 收集目标句子

一旦从原始句子中生成了一个相似的句子列表,下一步就是将所有的源句子输入到机器翻译软件中进行测试,并收集相应的翻译结果(即目标句子),随后分析结果以找出错误。他们使用谷歌和必应机器翻译系统作为实验的测试系统。为了获得翻译结果,他们调用谷歌翻译和微软必应翻译提供的 api,其返回的结果与它们的 Web 接口相同。

2.3 目标句的表示

接下来,必须对从被测试的转换系统中获得的目标句子进行建模,因为这允许他们比较结构以检测错误。选择表达句子的结构会影响进行有意义比较的能力。他们最终想要的是一种精确地为句子结构建模的表示,同时提供两个值之间的快速比较。

最简单和最快的方法是比较句子的原始形式:字符串。他们测试了这种方法,并证明了其性能是合理的。但是,在很多情况下,这种方法都不适用。例如,句子“on Friday, we went to the movies”中的介词短语“on Friday”也可以放在句子的末尾,如“we went to the movies on Friday”。句子是可以互换的,但是字符编辑距离之类的度量标准将表明字符串之间的巨大差异。语法解析克服了上述问题。使用语法分析器,可以对字符串的语法结构和单词或单词组之间的关系建模。例如,如果解析正确,上面的两个示例句子在关系值和解析结构方面应该具有相同的表示。

原始目标句。对于这个方法,他们将目标语句保留为其原始格式,即字符串。在大多数情况下,他们可能会认为,在用一种语言编写的句子中编辑单个标记将导致在已翻译的句子中更改单个标记。假设替换标记的语法角色是相同的,这在所有机器翻译系统中都是理想的。然而,在实践中并不总是这样,因为介词短语、修饰语和其他成分可以经常被翻译系统放置在不同的位置,并生成语义相同、语法正确的句子。不过,这种方法可以作为一个很好的基准。

选区解析树。部分解析是派生字符串语法结构的一种方法。它生成一组群体关系,显示一个词或一组词如何在一个句子中形成不同的单位。这组关系对于 SIT 特别有用,因为它将反映句子中短语类型的变化。选区关系可以可视化为一棵树,如图 4 所示。选区解析树是一种有序的根树,其中非终端节点是组成关系,终端节点是单词。在形式上,在群体解析中,句子根据给定的上下文无关语法所概述的短语结构规则被分解为它的组成部分。在实验中,使用了移位-减少选区解析器,并在斯坦福的 CoreNLP 库中实现,它每秒可以解析 50 个句子。

图 4.表示句子结构;依赖关系和选区关系都可以显示为树

依赖解析树。依赖解析同样派生字符串的语法结构。然而,所产生的关系集描述的是词语之间的直接关系,而不是词语如何构成一个句子。这组关系让我们对结构有了不同的见解,并且直观地对 SIT 很有用,因为它反映了单词之间如何相互作用的变化。在过去的 15 年中,依赖解析已经取得了很大的进展。基于神经网络的解析器的引入极大地提高了解析速度和准确性。与移位-减少选区解析器一样,基于神经网络的依赖关系解析器使用类似堆栈的系统,其中使用分类器选择转换。

在这种情况下,分类器是一个神经网络,同样训练在注释树银行。在实现中,他们使用了 Stanford CoreNLP 提供的最新的基于神经网络的解析器,每秒可以解析大约 100 个句子。此外,他们使用普遍的依赖关系作为注释方案,是基于斯坦福的依赖发展而来的。

2.4 通过结构比较检测翻译错误

最后,为了找出翻译错误,他们通过比较句子表征来寻找结构变异。无论句子被建模为原始字符串、单词嵌入或解析树,都有许多不同的度量来计算两个值之间的距离。这些度量标准往往是非特定于领域的,并且彼此之间可能具有较低的相关性,这使得度量标准的选择非常重要。例如,像 Word Mover's Distance 这样的度量将给一个距离为 0 的两个句子“He went to the store”和“store He the went to”,而字符编辑距离将给一个距离为 14。他们探索了几个不同的度量标准来评估句子之间的距离:字符编辑距离、选区集差异和依赖集差异。

原句之间的编辑距离。Levenshtein 距离通常称为“编辑距离”,它比较两个字符串,并通过计算将一个字符串转换为另一个字符串所需的最小字符编辑(删除、插入和替换)数量来确定它们之间的匹配程度。虽然该方法可能不能很好地展示句子之间的语法相似性,但它利用了这样一种预期,即编辑用一种语言编写的句子中的单个标记通常只会导致翻译句子中的单个标记的更改。因此,Levenshtein 距离可以作为一个很好的基线度量。

选区解析树之间的关系距离。为了评价两组选区关系之间的距离,将两组选区语法表之间的距离计算为每一种短语类型计数的绝对差的总和,从而对句子修改后的变化情况有一个初步的了解。这一启发式背后的动机是,一个句子的成分应该保持相同的两个句子之间只有一个标志的同一部分的词性不同。在一个健壮的机器翻译系统中,这也应该反映在目标句中。

依赖解析树之间的关系距离。类似地,为了计算两个依赖关系列表之间的距离,将每种依赖关系数量的绝对差相加。同样,其动机是当替换单个标记时,理想情况下单词之间的关系将保持不变。因此,在集合中的变化是合理的表明结构不变性已经被违反,推测有一个排序错误。

距离阈值。利用上述指标之一,计算原始目标句和生成的目标句之间的距离。然后必须决定修改后的目标句与其对应的原目标句是否相差甚远,足以表明存在翻译错误。要做到这一点,首先根据距离阈值进行过滤,只保留那些距离原始句子比所选阈值更远的句子。然后,对于给定的原始目标句,报告 top-k (k 也是一个选择参数)对目标句的最远修改。将距离阈值作为一个手动参数,因为用户可能根据他们的目标来优先考虑最小化假阳性报告或最小化假阴性报告。

3 评估

在本节中,通过将其应用于谷歌翻译和微软必应翻译,并使用从 Web 上抓取的真实世界未标记的句子来评估他们的方法。他们主要研究的问题是:

RQ1:在机器翻译软件中找到错误的翻译方法如何?

RQ2:该方法可以发现哪些翻译错误?

RQ3:这种方法的效率如何?

RQ4:在实践中如何选择距离阈值?

3.1 实验配置

为了验证 SIT 的结果,手动检查每个报告的问题,并共同决定:(1)问题是否包含有 bug 的句子;(2)如果是的,它包含怎样的翻译错误。

所有实验都是在 Linux 工作机上运行,配备 6 核 Intel Core i7-8700 3.2GHz 处理器,16GB DDR4 2666MHz 内存,GeForce GTX 1070 GPU。Linux 工作站运行 64 位 Ubuntu 18.04.02, Linux 内核为 4.25.0。

3.2 数据集

通常,为了测试机器翻译系统,开发人员可以采用 SIT,并将任何源句作为输入。因此,为了评估方法的有效性,他们从网络上收集真实世界的源句。具体来说,输入句子是从 CNN(有线新闻网)文章中提取的,分为政治和商业两大类。数据集是从两类文章中收集的,因为打算评估 SIT 是否在不同语义上下文的句子上始终表现良好。

对于每个类别,他们抓取了 10 篇最新的文章,提取了它们的主要文本内容,并将它们分割成一个句子列表。然后从每个句子列表中随机抽取 100 个句子作为实验数据集(共 200 个)。在这个过程中,包含超过 35 个单词的句子会被过滤,因为他们想要证明机器翻译软件即使对于相对简短的句子也会返回较差的结果。所收集数据集的详细信息如表 1 所示。

表 1.用于评价的输入句子的统计。每个语料库包含 100 个句子。

3.3 SIT 的有效性

该方法旨在使用未标记的句子自动查找翻译错误并报告给开发人员。因此,该方法的有效性在于两个方面:(1)报告的结果有多准确;(2)能找到多少错误的句子?在本节中,通过应用 SIT 来评估这两个方面,使用表 1 所示的数据集来测试谷歌翻译和微软必应翻译。

评估指标。SIT 的输出是一个问题列表,每个问题包含(1)一个原始的源句及其翻译:(2)top-k 报告生成的句子及其翻译(即:从源句翻译的 k 最远处翻译)。这里,将 top-k 准确度定义为在 top-k 所报告的句子或原始句子中至少有一个包含错误时所报告的问题的百分比。他们用这个作为 SIT 的精度度量。

结果。Top-k 准确性。结果如表 2 所示。SIT (原始)、SIT(选区)和 SIT(依赖性)是 SIT 实现,它们分别以原始句子、选区结构和依赖结构作为句子结构表示。表中的每个项都显示了 top-k 精度以及发现的错误问题的数量。在随后的讨论中,为了简洁起见,将 SIT(选区)和 SIT(依赖性)分别称为 SIT (Con)和 SIT (Dep)。

表 2.SIT 的 top-k 准确度

他们观察到 SIT (选区)和 SIT (依赖性)始终比 SIT (原始)表现得更好,这说明了句子结构表征的重要性。在 SIT (原始)中使用的度量仅仅基于句子中的字符,是脆弱的,容易出现过多或过少的报道错误。特别是,在测试微软必应翻译时,SIT (依赖)报告了 100 个可疑问题。在这些错误中,有 70 个错误是在第一个报告句子或原文中出现的翻译错误,其准确度达到 70%的第一名。SIT (依赖)在谷歌翻译和必应微软翻译中都有最好的性能。它成功地找到 64 个和 70 个错误问题,准确率分别为 69.5%和 71%。

此外,他们还研究了 SIT 是否会在生成的句子中引发新的错误。如表 3 所示,在所报告的问题中,谷歌翻译和微软必应翻译器对原句的翻译分别出现了 55 和 60 个独特错误。除了这些错误之外,SIT 还发现 79 和 66 个额外的唯一错误,这些错误只在生成的句子对中显示,而在原始句子中没有。因此,考虑到它极高的 top-k 精度和大量额外的独特错误报告,相信 SIT 在实践中非常有用。

表 3.唯一错误的数量

3.4 SIT 报告的翻译错误

SIT 能够发现各种翻译错误。在谷歌翻译和微软必应翻译器的实验中,他们主要发现了 5 种翻译错误:翻译不足、翻译过度、修改错误、词/短语误译、逻辑不清。错误类型来源于机器翻译的错误分类方法。这五种错误中的每一种都是词法错误、语法错误或语义错误的子集。本节重点介绍了所有 5 种错误的示例。表 4 给出了找到的翻译错误的统计数据。SIT 发现的大部分翻译错误都是由于翻译不足、词/短语错译和逻辑不清楚造成的。

表 4.在每个类别中有特定错误的句子的数量

翻译不足。如果有些词没有翻译(即没有出现在翻译中),这是翻译不足的错误。图 5 给出了一个包含翻译错误的句子对。在这个例子中,“to Congress”没有被错误地翻译出来,导致目标句的语义意义不同,“lie to Congress”是违法的,而“lie”只是一种不恰当的行为。

图 5.检测到翻译不足错误的示例

过度翻译。如果有些词不必要地多次翻译,或者目标句中的一些词不是从源句中的任何一个词翻译过来的,这就是过度翻译错误。在图 6 中,目标句中的“thought”并不是由源句中的任何单词翻译而来的,这是一种过度翻译的错误。有趣的是,他们发现过度转换错误经常伴随着一些其他类型的错误发生。该示例还包含一个翻译不足的错误,因为源句中的“were right”错误地没有翻译。

图 6.检测到的过度转换错误示例

不正确的修改。如果某些修饰语在句子中修改了错误的成分,这是一种错误的修饰语错误。在图 7 中,修饰语“new”修饰源句中的“auto manufacturing”。但是,谷歌翻译认为“new”应该修改“hub”。

图 7.检测到的不正确修改错误示例

词/短语误译。如果在目标句中出现了一些符号或短语的翻译错误,那就是词/短语错译错误。图 8 给出了这类错误的两个主要子类别:(1)一词多义的歧义和(2)翻译错误。

一词多义的模棱两可。每个符号/短语可能有多个正确的翻译。例如,admit 的意思是“允许某人加入一个组织”或“勉强同意某事”。然而,通常在特定的语义语境中(例如,一个句子),一个标记/短语只有一个正确的翻译。现代翻译软件对一词多义的处理效果并不理想。在图 8 中的第一个例子中,谷歌翻译认为源句中的“admit”指的是“勉强同意某事”,导致了符号/短语误译的错误。

错误的翻译。一个标记/短语也可能被错误地翻译成另一个语义上似乎不相关的意思。例如,图 8 中的第二个例子中,微软必应翻译认为“South”指的是“South Korea”,导致了一个单词/短语的误译。

图 8.图 9:检测到的单词/短语误译错误示例

不清楚逻辑。如果所有的符号/短语翻译正确,但句子逻辑不正确,这是一个不清楚的逻辑错误。在图 9 中,谷歌翻译正确的翻译了“serve In the elected office”和“country”,但是谷歌翻译产生了“serve In the elected office as a country”而不是“serve In the country In elected office”,因为谷歌翻译不理解两者之间的逻辑关系。NMT 模型的翻译中普遍存在逻辑不清的错误,这在一定程度上反映了模型是否真正理解了某些语义。

图 9.检测到逻辑错误不清楚的例子

句子翻译错误多。所报告的句子对中有一定比例包含多个翻译错误。图 10 给出了一个包含三种错误的句子对。具体来说,源句中的“cover”指的是“报道新闻”。但是,它被翻译成“hold”,导致了一个词/短语的误译。此外,目标句中的“church”并不是源句中任何一个词的翻译,是一种过度翻译的错误。微软必应翻译也误以为主语是“参加葬礼火车”。但是原句的意思是主语是“报道葬礼火车”,所以这是一个不清楚的逻辑错误。

图 10.检测到多个翻译错误的句子示例

3.5 SIT 的运行时间

在本节中,将评估 SIT 在两个数据集上的运行时间。他们使用 3 种不同的句子结构表示 SIT 来测试谷歌翻译和微软必应翻译。他们将每个实验设置运行 10 次,并报告其平均值作为结果。SIT 的总体运行时间如表 5 所示,SIT 在谷歌翻译上每一步的运行时间如图 11 所示(必应的结果与此相似)。我们可以看到,SIT 使用原始句子作为结构表征是最快的。这是因为 SIT (原始)不需要任何结构表示生成时间,使用依赖解析器可以获得与 SIT(原始)相当的运行时间。特别是,SIT (依赖)使用 19 秒解析 2000+个句子,认为这是高效和合理的。

表 5.SIT 在政治和商业数据集中的平均运行时间

图 11.测试谷歌翻译时 SIT 的运行时间细节(不包括翻译时间)

3.6 距离阈值的影响

如果翻译生成的句子和原始目标句子之间的距离大于距离阈值,SIT 就会报告问题中的 top-k 句对。因此,这个距离阈值控制(1)报告的 bug 问题的数量和(2)SIT 的 top-k 精度。直观地说,如果降低阈值,将报告更多的错误问题,但准确性将下降。基于实验结果,他们给出了一些实际使用 SIT 的指导。首先,如果打算发现尽可能多的翻译错误,应该使用一个小的距离阈值。其次,如果想让 SIT 尽可能精确,可以使用一个较大的阈值。当阈值较大时,SIT 报告的问题更少,但准确性非常高。考虑到网络上源句的数量是无限的,可以在很大的距离阈值下运行 SIT,并定期报告问题。因此,他们认为 SIT 在实践中是有效且容易使用的。

3.7 使用 SIT 报告的错误

在本节中,我将研究所报道的错误句子是否可以作为一个微调集来提高 NMT 模型的鲁棒性。微调是 NMT 中常见的做法,因为训练数据和目标数据往往会占据不同的领域。

为了测试 NMT 模型,SIT 在 40 个英语句子上运行,这些句子是从 WMT 17 的验证集中通过删除长句子(即。大于 12 个单词),并确保所有单词都在 NMT 模型的词汇表中。注意,由于模型没有在来自该领域的数据上进行训练或验证,因此我们模拟了实际场景,其中真实世界的输入与模型训练数据不同。根据这些输入,SIT 成功地找到了 105 个有错误的句子。用正确的翻译对它们进行了标注,并对这 105 个句子进行了 15 个时期的 NMT 模型微调,学习率降低。经过这次调整,105 个句子都能被正确翻译。同时,训练中使用的原验证集的 BLEU 分数提高了 0.13,这在一定程度上说明其他句子的翻译也得到了提高。这展示了以高效和简单的方式修复 SIT 报告的错误的能力。

4 讨论

4.1 假阳性

SIT 可以准确检测翻译错误,其精度可以进一步提高。特别是,SIT 的假阳性有三个主要来源。首先,生成的句子可能会产生奇怪的语义,导致目标句的结构发生变化。例如,基于短语“on the fact”,SIT 的当前实现可以生成句子“on the fact”,这自然会有非常不同的中文翻译。使用 BERT 帮助缓解了这个问题。在实验中,BERT 提供了 MLM 模型。其次,尽管现有的语法解析器非常精确,但它们可能产生错误的选区或依赖结构,从而导致错误的报告错误。第三,一个源句可以有多个不同句子结构的正确翻译。例如,目标句“10 years from now”和“after 10 years”,虽然句子结构不同,但可以互换使用。为了降低这些因素的影响,SIT 按与原始目标句的距离排列,返回前 k 个可疑句对。

4.2 构建健壮的翻译软件

与测试传统软件类似,测试机器翻译的最终目标是构建健壮的软件。为此,SIT 的效用如下。首先,所报告的误译通常作为早期警报,因此开发人员可以提前硬编码翻译映射,这是业界采用的最快的错误修复解决方案。第二,所报告的句子可以用作微调集。第三,开发人员可能会发现报告的有问题的句子对进一步分析/调试很有用,因为每对句子中只有句子相差一个字。这类似于通过输入最小化/本地化来调试传统软件。

5 总结

本文提出了一种新的、有效的机器翻译软件测试方法——结构不变测试(SIT)。SIT 的显著优点是它的简单性和通用性,因此具有广泛的适用性。SIT 已经被用于测试谷歌翻译和微软必应翻译器,并成功找到 64 个和 70 个有 bug 的翻译器,准确率分别为 69.5%和 70%。此外,作为一种通用的翻译方法,SIT 可以发现各种先进的翻译方法无法发现的翻译错误。我们相信,这项工作是走向机器翻译软件的系统测试的重要的第一步。

本文由南京大学软件学院 2023 级硕士何云转述

免费英语句子分析器(希伯来大学)

ACL 2023 Long Papers

使用语义和神经网络方法进行简单有效的文本简化

Simple and Effective Text Simplification Using Semantic and Neural Method

耶路撒冷希伯来大学

The Hebrew University of Jerusalem

本文是耶路撒冷希伯来大学发表于 ACL 2023 的工作,本文提出了一种简单有效的基于自动语义解析的分割算法。分割之后,文本可以进行进一步的微调简化操作,在这种情况下可以有效地使用神经机器翻译。机器翻译在简化任务上的早期应用存在一个不可忽视的缺点,那就是过于保守,经常不能以任何方式修改源代码。本文提出的基于语义解析的拆分方法有效避免了这个问题。实验表明该方法在词法和结构简化的组合方面都优于目前的最好方法。

1 引言

文本简化(TS)一般被定义为将一个句子转换成一个或多个简单的句子。在诸如机器翻译和关系提取,以及阅读辅助工具开发(例如,对于有阅读障碍的人或非母语者)的预处理步骤等任务中,都已被证明是非常有用的。TS包括结构化和词汇化运算。核心的结构简化操作是句子切分,即将一个句子重写成多个句子,同时保留其原始含义。虽然最近使用神经MT(NMT)方法已经取得了巨大进展,但是这些系统并没有解决句子切分的问题,主要是由于训练语料库中这种情况比较的罕见。

我们发现在简化系统中显式地集成句子切分可以缓解基于NMT的TS系统的保守性,它严重影响了模型效能。的确,用最先进的神经系统进行实验,我们发现66%的输入句子保持不变,而没有相应的引用与源相同。通过人工和自动评估,确认参考文献确实比源文献简单,这也表明观察到的保守性是过度的。本文方法使用句子分割进行预处理,允许TS系统执行其他操作(例如,删除)和词汇(例如,单词替换)操作,从而提升了结构和词汇的简化性。

本文首次将结构语义学与神经网络方法相结合,提出了基于语义解析的直接语义切分(DSS)算法,它是一种简单、高效的基于语义解析的算法,支持将句子分解为多个核心语义成分。分割之后,使用NTS系统执行基于NMT的简化。实验表明本文方法优于现有领先方法。本文使用UCCA方法进行语义表示,进一步利用UCCA中场景(事件)类型的明确区别,为每个场景应用特定规则。

2 模型

语义表示

UCCA是一种植根于类型学和认知语言学理论的语义标注方案。它旨在展示文本中的主要语义现象,从句法形式中抽象出来。在翻译任务中,已经证明了UCCA在语义保存上做得非常好,并且已经被成功地用于机器翻译的评估,并且最近成功地应用于TS评估和语法纠错。

场景是UCCA关于事件或框架的概念,指的是一些持续存在的运动、动作或状态单元。每一个场景都包含一个主要的关系,它可以是一个过程,也可以是一个状态。场景包含一个或多个参与者,广义上包括位置和目的地。例如,句子“He went to school”只有一个场景,其过程是“went”。两个参与者是“He”和“to school”。

场景可以在文本中有多个角色。首先,它们可以提供关于已建立的实体(精细化场景)的附加信息,通常是分词或关系子句。例如,“(child) who went to school”是“The child who went to school is John”中的精细化场景(“孩子”既是精细化场景中的论点,也是中心)。场景也可以是另一场景中的参与者。例如,句子“He said John went to school” 中的“John went to school”。在其它情况下,场景被标注为平行场景(H),它是扁平结构,可以包括连接器(L),如:“WhenL [he arrives]H , [he will call them]H”。

对于那些不是场景的单元,类别中心表示语义头部。例如,“dogs”是“big brown dogs”的表达中心,“box”是“in the box”的中心。在一个单元中可能有一个以上的中心,例如在coordination的情况下,所有的结点都是中心。我们将UCCA单元u的最小中心定义为UCCA图的叶子,从u开始,迭代地选择标记为中心的子节点。

为了生成UCCA结构,本文使用一个基于转换的解析器TUPA(具体地,TUPABiLSTM模型)。TUPA使用一组变换表达组合,能够支持UCCA方案所要求的结构特性。给定词嵌入和其他特征,其变换分类器是基于接收解析器状态(缓冲区、堆栈和中间图)元素BiLSTM编码的MLP。

语义规则

为了执行DSS,我们在UCA范畴的条件下定义了两个简单的切分规则。目前我们只考虑平行场景和精细化场景,不分离参与场景,以避免在名词化或间接讲话的情况下切分。例如,句子“His arrival surprised everyone”,除了“surprised”引发的场景之外,“arrival”引发的参与场景在这里没有切分。

规则#1:提取给定语句的并行场景,分隔成不同的语句,并根据出现顺序进行连接。给定将句子S分解为并行场景

(按第一个token的顺序索引),我们得到以下规则,其中“|”是句子分隔符:

由于UCCA允许场景之间的参数共享,所以规则可以在语句之间复制相同子跨度S。例如,这个规则会把“He came back home and played piano”变成“He came back home”|“He played piano.”。

规则#2:给定一个句子S,第二条规则提取精细化场景和相应的最小中心。然后将精细化场景连接到原始语句,其中除阐述最小中心的精细化场景外,其他的都被删除。代词如“who”、“which”和“that”也被删除。

形式上,如果

是S及其对应的最小中心的精细化场景,重写为:

其中S-A指的是没有单元A的S。例如,这条规则将“He observed the planet which has 14 known satellites”的句子转换为“He observed the planet| Planet has 14 known satellites.”。文章重组不被规则覆盖,因为它的输出被直接送到NMT组件中。

在提取并行场景和精细化场景之后,将得到的简化并行场景放置在精细化场景之前。请参阅图1。

神经单元

句子切分是通过NTS状态的最先进的神经TS系统,使用OpenNMT神经机器翻译框架构建的。该体系结构包括两个LSTM层,每个隐藏状态包含500个单元,以及与输入相结合的全局注意力机制。训练以0.3的dropout概率完成。该模型使用预测句与原句之间的对齐概率,而不是基于字符模型来检索原始单词。

本文考虑W2V初始化NTS(N17),其中word2vec词向量的大小为300,使用谷歌新闻进行训练,本地词向量大小设置为20,在简化语料上进行训练。编码器的局部词嵌入在训练语料库的源端进行训练,而解码器的局部词嵌入在简化端进行训练。

为了采样来自系统的多个输出,解码期间,在给定输入句子的目标句子进行对数似然度排序,通过每个步骤生成前5个假设来执行集束搜索。我们在此探索最高(h1)和第四级(h4)假设,这说明增加了SARI评分,而且不那么保守。因此我们用NTS-h1和NTS-h4表示的神经成分的两个变体进行实验。规则和神经系统的两个相应的模型:SENTS-h1和SENTS-h4。

3 实验

语料库:所有系统的测试语料库来自2023年的Optimizing statistical machine translation for text simplification论文中提出的语料集,包括359个从PWKP语料库中,通过众包收集的8篇参考文献。

语义部分:TUPA 解析器是在UCCA标注的Wiki语料库上进行训练的。

神经成分:使用N17提供的NTS-w2v模型。训练集基于标准英语维基百科和简单英语维基百科之间的手动和自动对齐,它们的相似性分数高于0.45。训练集的总大小约为280K个对齐句子,其中150K个句子为完全匹配,130K个句子为部分匹配。

启发式问题在下表中给出。

根据前人工作研究,语法(G)和意义保存(M)使用1到5的尺度来测量。请注意,在第一个问题中,没有考虑输入语句。通过评估Identity转换(参见下表)来评估输入的语法性,从而为其他系统的语法性分数提供基线。

结果如下表所示。Identity获得比任何其他系统高得多的BLEU得分,这表明BLEU可能不适用这个设置。SARI似乎更具信息量,并将最低分数分配给identity,次高分配给reference。

Moses的不同组合与DSS的评价结果如下。

系统输出的一个测试句子与相应的人类评估分数(平均3个标注者)。

人工评价使用人工UCCA标注,语法(G)含义保存(M)使用1到5的规模量化。输出句子的简洁性(S)和结构性(StS)使用-2到+2规模进行量化。Xm指的是系统X的半自动版本。

4 总结

本文提出了一种语义结构和神经机器翻译相结合的简化系统,实验表明它优于现有的词法和结构系统。所提出的方法解决了基于MT的TS系统过于保守的问题,TS系统通常不能以任何方式修改源。语义组件进行句子切分可以不依赖于专门的语料库,而仅依赖于现成的语义分析器。考虑将句子切分看作把句子分解为多个场景,进一步将SAMSA度量假设应用于不同目的(TS体系结构和TS评价),验证了其有效性。未来的工作将利用UCCA的跨语言适用性来支持MT\的多语言TS和TS预处理。

论文下载链接:

http://aclweb.org/anthology/P18-1016

以上内容是关于免费英语句子分析器和阿里p8和mysql哪个好的内容,小编幸苦为你编辑整理,喜欢的请点赞收藏把。

标签:阿里p8和mysql哪个好

标题:免费英语句子分析器 阿里p8和mysql哪个好

链接:http://m.zhaichaow.cn/z/1636217.html