作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
列昂尼德·德拉金斯基的头像

列昂尼德•Draginsky

Leonid有20多年的多平台开发和DBA经验, 在Oracle和SQL Server跨平台迁移方面具有特殊的专业知识.

以前在

J.P. Morgan Chase)
分享

本系列的第一部分 讨论了 Oracle数据库Microsoft SQL Server 在执行交易时, 重点是在Oracle到SQL Server迁移过程中可能遇到的陷阱,反之亦然. 下一期将介绍一些常用的SQL语法元素,这些元素在oracle和SQL Server之间没有匹配,或者具有完全不同的含义或用法.

Oracle中的序列和SQL Server中的标识列

长期存在的分歧 在数据库社区中有两个阵营:自然键的支持者和人工键(或“替代”键)的支持者.

我自己为自然键辩护,但经常发现自己出于这样或那样的原因创建了替代品. 但先不谈这场辩论的实质, 让我们看看生成人工键的标准机制:Oracle序列和SQL Server标识列.

Oracle序列是一级数据库级对象. 相反,SQL Server标识列是一种列类型,而不是对象.

当使用Oracle序列生成表键(通常是主键)时,它保证是递增的, 因此是独一无二的. 但它是 保证连续. 事实上,即使在设计良好的实现中,也很可能存在一些差距. 因此任何Oracle实现都不应该依赖于序列生成的值是连续的.

也, 序列通过Oracle数据库的数据字典进行管理, 因此,创建一个专门的序列来支持每个代理键将会非常耗费资源(而且很麻烦). 单个序列对象可以支持多个甚至所有代理键.

另一方面,当多个进程需要访问时 NEXTVAL (下一个增量值)从一个序列, 这个顺序将成为一个关键, 单址资源. 它将有效地使访问它的所有进程严格按顺序进行, 将任何多线程(单服务器或多服务器)实现转换为单线程进程, 具有长等待时间和高内存/低CPU使用率.

这样的实现确实发生了. 这个问题的解决方案是用合理的缓存值来定义有问题的序列对象,这意味着一个定义的值范围(可能是10个或10万个)被选择到一个调用进程的缓存中, 按使用情况记录在数据字典中, 并且可以用于这个特定的进程,而不需要每次都访问数据字典 NEXTVAL 被称为.

但这正是为什么空白将被创建,因为不是所有的缓存值可能被使用. 这也意味着跨并行会话中的多个进程, 一些记录的序列值可以按时间顺序倒转. 除非序列值被重置或倒移,否则这种反转不会在单个进程中发生. 但最后一种情况相当于自找麻烦:它应该是不必要的, 如果执行不正确, 它可能导致生成重复的值.

So, 使用Oracle序列的唯一正确方法是生成代理键:这些键是唯一的,但不被认为包含任何其他可靠的可用信息.

SQL Server中的标识列

SQL Server怎么样?? 而序列的功能和实现与Oracle序列非常相似 在SQL Server 2012中引入的在美国,它们不是一流的常用技术. 像其他添加的功能一样, 从Oracle转换过来是有意义的, 但是当在SQL Server上从头开始实现代理键时, 身份 是更好的选择吗.

身份 是表的“子”对象吗. 它不访问表外的资源,并且保证是顺序的,除非有意操作. 它是专门为这个任务设计的, 而不是为了与Oracle的语义兼容.

Oracle已经实现了 身份 版本12的功能.1, 人们很自然地会想,没有它以前会怎么样, 为什么现在才实施呢, 以及为什么SQL Server从一开始就需要它(从它的Sybase SQL Server起源).

原因是Oracle一直有一个身份关键特性: ROWID 伪列,数据类型为 ROWID or UROWID. 该值是非数字的(ROWIDUROWID 是专有的Oracle数据类型吗),并唯一标识数据记录.

不像SQL Server 身份,甲骨文的 ROWID 不能被轻易操纵(可以被查询, 但不能插入或修改), 它是在后台为每个Oracle表的每一行创建的. 此外,访问Oracle数据库中任何数据行的最有效方法是通过其 ROWID因此,它被用作性能优化技术. 最后, 它定义了默认的查询输出排序顺序, 因为它有效地索引了行数据的低级存储.

如果甲骨文 ROWID 如此重要,SQL Server是如何在没有它的情况下存活这么多年的? 通过使用 身份 列作为主(代理)键.

注意Oracle和SQL Server在索引结构实现上的不同是很重要的.

在SQL Server中, 第一个索引——主键, more often than 不—is clustered; this means that most commonly, 主数据文件中的数据按此键排序. 在Oracle端,相当于聚集索引的是索引组织表. 在Oracle中,这是一个可选的结构,偶尔使用, 仅在需要时使用—只读查找表, 例如.

在Oracle中所有的设计模式都是基于使用的 ROWID (如重复数据删除)应基于 身份 列迁移到SQL Server时.

在从使用 身份 在SQL Server上使用 身份 不能生成功能正确的代码,这不是最优的,因为在Oracle这边, ROWID 会更有效率吗.

当进行简单的SQL语法转换以将Oracle序列移动到SQL Server中时也是如此:代码将运行, 但使用 身份 在代码简单性和性能方面,是更受欢迎的选项吗.

Microsoft SQL Server中的过滤索引

年前, Microsoft SQL Server 2008引入了许多重要的特性,使其成为真正一流的企业数据库. 一个不止一次拯救过我的人 过滤索引.

过滤索引是非聚类索引(例如.e.(作为自己的数据文件存在),该文件具有 在哪里 条款. 这意味着索引文件只包含与子句相关的数据记录. 为了充分利用过滤索引,它还应该有一个 包括 子句,该子句列出返回数据集时所需的所有列. 当您的查询被优化为使用包含所有所需数据点的特定过滤索引时, 数据库引擎只需要访问一个(小的)索引文件,甚至不需要查看主表数据文件.

几年前,当我处理tb大小的表时,这对我来说特别有价值. 所讨论的客户机在任何给定时间通常只需要访问活动记录的一小部分. 这种访问的最初实现(由最终用户UI操作触发)不仅非常缓慢,而且完全无法使用. 当我添加了一个带有所需的过滤索引时 包括S,它变成了亚毫秒级的搜索. 我花在这个优化任务上的时间只有一个小时.

当然,过滤索引有一些限制. 它们不能包括LOB列,在什么条件下有限制 在哪里 索引本身可以包含子句,它们会增加数据库的存储占用. 但是提供一个符合这些参数的用例, 与过滤索引所能提供的显著性能提升相比,存储方面的折衷通常是微不足道的.

Oracle数据库中的过滤索引是什么?

后来,我在一家财富500强公司的一个大型团队中担任SQL server到oracle迁移项目的开发人员/DBA. 围绕源数据库(sql Server 2008)的代码实现得很差, 性能低下,使得转换势在必行:每日后端同步作业的运行时间超过23小时. 它没有过滤索引, 而是在新的oracle 11g系统中, 在很多情况下,我看到过滤索引非常有用. 但是Oracle 11g没有过滤索引!

在最新的Oracle 18c中也没有实现过滤索引.

但作为专业技术人员,我们的任务是充分利用现有资源. 因此,我在Oracle 11g系统中实现了与过滤索引相当的功能(以及我后来在Oracle 11g系统中使用的相同技术). 这个想法是基于Oracle的处理方式 s,可以在任何版本的Oracle中使用.

Oracle不治疗 值的方式与常规数据相同. A 在Oracle中是空的——它不存在. 因此,如果将索引列定义为 可以为空 你是通过非来搜索的 值,则索引数据文件将只包含感兴趣的记录. 作为一个Oracle索引定义没有 包括 条款, 您需要创建一个复合索引,其中包含需要包含在结果集中的所有列. (与SQL Server相比,这种技术有一些开销 包括 条款,但它是相当微不足道的.)

这种变通实现确实增加了一个限制:首索引列必须允许 S,因此不能作为表的主键. 然而,它 可以 是专门为支持此性能优化方法而创建的派生列或计算列. 在某种意义上,索引的前导列在逻辑上是二进制的:non- 值表示搜索中包含的数据,以及 对于任何应该“不可见”的数据.”

将SQL Server过滤索引逻辑迁移到Oracle的另一个可能的选择是将索引(或完整的表)实现为分区. 在这种情况下, 只有相关的索引分区才能被数据库引擎访问——前提是查询通过在索引分区中使用精确的分区条件来正确实现 在哪里 条款.

这样会很好, 即使在规模上, 关于相对静态的数据, 但如果应用于频繁变化的数据,可能会给DBA团队带来很高的维护负荷. 在以时间为中心的应用程序中优化对当前数据的访问就是一个例子:DBA团队需要每天重新定义分区. 虽然这种重新定义可以在夜间维护工作中编写脚本, 它确实会使您的系统更加复杂,并引入新的潜在系统故障点.

So, 当需要将SQL Server过滤索引逻辑迁移到Oracle时,需要非常具体和小心.

如何处理转换

用Oracle迁移到SQL Server, 寻找使用过滤索引进行优化的机会. 在Oracle中您不会看到过滤索引,但是您可能会看到包含以下内容的索引 值. 不要原样复制它们:这可能是你在转换过程中获得性能提升和设计改进的最佳地方.

用于SQL Server到Oracle的迁移, 如果您看到过滤的索引, 在相应的Oracle代码中查找如何避免性能瓶颈. 了解如何重新设计数据流,以补偿源实现中过滤索引所带来的性能提升.

SQL Server到Oracle / Oracle到SQL Server迁移挑战揭秘

用于Oracle和SQL Server之间的任意方向的迁移项目, 更深入地理解所涉及的机制非常重要. 当当前版本的数据库(Oracle 18c和Microsoft SQL Server 2017*)包含彼此功能的词法等效时- e.g.在顺序和身份方面,这似乎是一场轻松的胜利. 但是,将一个RDBMS上的良好设计直接复制到另一个RDBMS上可能会导致不必要的复杂和性能低下的代码.

In 本系列的下一部分也是最后一部分,我将介绍读取一致性和迁移工具的使用. 请继续关注!

* SQL Server 2019(或“15 . SQL”.X”)问世的时间还不够长,不足以让企业广泛采用.

关于总博客的进一步阅读:

了解基本知识

  • 什么是Oracle序列周期?

    An Oracle sequence cycle allows a sequence to restart when 的 whole range of 值 is used; this implies that 的 sequence 可以 create duplicate 值 overall. NOCYCLE不允许复制,但如果所有值都已使用,则返回错误.

  • 身份列在SQL Server中是如何工作的?

    SQL Server中的SQL标识列有一个值,该值在插入新行时自动增加. 不能编辑SQL标识列值.

  • 什么是数据库中的标识列?

    SQL标识列是具有自动递增的大整数(“bigint”)值的列.

  • 什么是SQL Server中的过滤索引?

    SQL Server中的过滤索引是带有在哪里子句的索引.

  • 什么是SQL数据转换?

    数据转换是一种更改值的数据类型的操作. 示例:将字符串/字符数据转换为数字或日期.

  • 什么是SQL Server键?

    键是在SQL Server表中唯一标识一行的值.

聘请Toptal这方面的专家.
现在雇佣
列昂尼德·德拉金斯基的头像
列昂尼德•Draginsky

位于 韦斯特维尔,俄亥俄州,美国

成员自 2020年6月18日

作者简介

Leonid有20多年的多平台开发和DBA经验, 在Oracle和SQL Server跨平台迁移方面具有特殊的专业知识.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

以前在

J.P. Morgan Chase)

世界级的文章,每周发一次.

订阅意味着同意我们的 隐私政策

世界级的文章,每周发一次.

订阅意味着同意我们的 隐私政策

Toptal开发者

加入总冠军® 社区.