首页 > 数据库 >Oracle 与 GreatSQL 差异:更改唯一索引列

Oracle 与 GreatSQL 差异:更改唯一索引列

时间:2024-11-09 17:57:29浏览次数:1  
标签:test1 GreatSQL update 索引 Oracle com row

Oracle 与 GreatSQL 差异:更改唯一索引列

  1. 问题来源
    在从 Oracle 迁移到 GreatSQL 的应用系统中,一条普通的 update 语句在 GreatSQL 中却报错,需要进行 SQL 语句的改写。把实际问题简化为下面简单情况进行说明。

在 Oracle 下,可以正常执行的 update 语句。

-- 建表
CREATE TABLE test.test1 (
id INT PRIMARY KEY,
k INT NOT NULL,
c CHAR(120) NOT NULL,
pad CHAR(60) NOT NULL
);

-- 创建唯一索引
CREATE UNIQUE INDEX ui_test1_k ON test.test1 (k);

-- 插入数据
INSERT INTO test.test1 VALUES
(1, 1, 'cc', 'pad'),
(2, 2, 'cc', 'pad'),
(3, 3, 'cc', 'pad'),
(4, 4, 'cc', 'pad');

-- 执行 UPDATE 语句
UPDATE test.test1 SET k = k + 1;
UPDATE test.test1 SET k = k - 1;
在 GreatSQL 下准备测试表和数据:

CREATE TABLE test1 (
id int NOT NULL AUTO_INCREMENT,
k int NOT NULL DEFAULT '0',
c char(120) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
pad char(60) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
PRIMARY KEY (id),
UNIQUE KEY ui_k (k)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

greatsql> INSERT INTO test1 VALUES (1, 1, 'cc', 'pad');
greatsql> INSERT INTO test1 VALUES (2, 2, 'cc', 'pad');
greatsql> INSERT INTO test1 VALUES (3, 3, 'cc', 'pad');
greatsql> INSERT INTO test1 VALUES (4, 4, 'cc', 'pad');
同样的 update 语句,在 GreatSQL 下执行报错:

greatsql> UPDATE test1 SET k = k + 1;
ERROR 1062 (23000): Duplicate entry '2' for key 'test1.ui_k'
在 GreatSQL 下,UPDATE 语句为什么报错呢?使用什么方法可以高效执行呢?

  1. 解决方法
    由 UPDATE 语句的报错可知是唯一键重复的问题,将 k=1 的行更改 k=k+1=2,与 k=2 的行重复。解决方法有 2 个方向:

让唯一索引暂时失效,update 完成后再启用
让数据按一定的顺序执行,避免数据重复
尝试设置 unique_checks 为 0
设置会话系统变量 unique_checks=0,则允许存储引擎假定输入数据中不存在重复的键。如果您确定您的数据不包含唯一性冲突,那么您可以将它设置为 0,以加快将大型表导入 InnoDB 的速度。将此变量设置为 0 并不要求存储引擎忽略重复的键。仍然允许引擎检查它们,并且如果它检测到它们,就发出重复索引的错误。

实际测试,设置 UNIQUE_CHECKS=0,update 语句仍然报错。

greatsql> SET UNIQUE_CHECKS=0;
Query OK, 0 rows affected (0.00 sec)

greatsql> UPDATE test1 SET k = k + 1;
ERROR 1062 (23000): Duplicate entry '2' for key 'test1.ui_k'
方法 1:删除唯一索引,update 后重建
删除唯一索引,update 后重建唯一索引的方法,有 2 个 DDL 操作,由于 DDL 前会自动提交事务,这种处理方法不能和其他操作在同一个事务中,同时也存在 update 后(有重复值)无法创建唯一索引的风险。适合数据的手工一次性处理。

greatsql> ALTER TABLE test1 DROP index kc;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0

greatsql> UPDATE test1 SET k=k+1 ;
Query OK, 100 rows affected (0.01 sec)
Rows matched: 100 Changed: 100 Warnings: 0

greatesql> ALTER TABLE test1 ADD UNIQUE key ui_k(k);
Query OK, 0 rows affected (0.09 sec)
Records: 0 Duplicates: 0 Warnings: 0
方法 2:update 按顺序执行
可以在 update 语句中使用 order by 子句,按照 k 值顺序执行,避免 update 后的数据与原有数据重复。

k=k+1时,需要按照降序执行

greatsql> UPDATE test1 SET k=k+1 ORDER BY k DESC;
Query OK, 4 rows affected (0.01 sec)
Rows matched: 4 Changed: 4 Warnings: 0

greatsql> UPDATE test1 SET k=k+1 ORDER BY k ;
ERROR 1062 (23000): Duplicate entry '2' for key 'test1.ui_k'

k=k-1时,需要按照升序执行

greatsql> UPDATE test1 SET=k-1 ORDER BY k ;
Query OK, 4 rows affected (0.01 sec)
Rows matched: 4 Changed: 4 Warnings: 0

greatsql> UPDATE test1 SET k=k-1 ORDER BY k DESC;
ERROR 1062 (23000): Duplicate entry '4' for key 'test1.ui_k'
执行效率对比
对比方法 1 和方法 2 的执行效率。

方法1:删除唯一索引,UPDATE后重建

greatsql> ALTER TABLE test1 DROP index k;
Query OK, 0 rows affected (0.17 sec)
Records: 0 Duplicates: 0 Warnings: 0

greatsql> UPDATE test1 SET k=K+1;
Query OK, 1000000 rows affected (35.08 sec)
Rows matched: 1000000 Changed: 1000000 Warnings: 0

bk.51yjjy.com/0wSwf.Wap
bk.sdymsxfh.com/fX8Xw.WaP
bk.bjyins.com/jasl/c4FSw.wAp
bk.testoppo.com/asd7/c5W4R.WAp
bk.zcyxsm.com/c4FSw.wAp
bk.jyh01.com/deyz/fX8Xw.WaP
bk.shplcchina.com/cliq/c4FSw.wAp
bk.lovehua99.com/jasl/fX8Xw.WaP
bk.huaxinlighting.com/fX8Xw.WaP
bk.shplcchina.com/cliq/f8W4d.wAP
bk.huaxinlighting.com/asd7/fX8Xw.WaP
bk.huaxinlighting.com/cliq/0wSwf.Wap
bk.tanjiuspace.com/asd7/c4FSw.wAp
bk.jyh01.com/f8W4d.wAP
bk.lovehua99.com/meyl/fX8Xw.WaP
bk.jiaforhui.com/dcwl/f8W4d.wAP
bk.51yjjy.com/dcwl/c5W4R.WAp
bk.qcbysq.com/beyn/f8W4d.wAP
bk.tanjiuspace.com/D30eq.wAP
bk.shplcchina.com/jasl/D30eq.wAP

greatsql> ALTER TABLE test1 ADD UNIQUE index kc(k,c);
Query OK, 0 rows affected (12.35 sec)
Records: 0 Duplicates: 0 Warnings: 0

方法2:UPDATE按顺序执行

greatsql> UPDATE test1 set k=K+1 ORDER BY k DESC;
Query OK, 1000000 rows affected (1 min 36.81 sec)
Rows matched: 1000000 Changed: 1000000 Warnings: 0
总结:执行时间 方法 1: 方法 2=47.50 : 96.81 = 1 : 2.04 ,方法 1(删除唯一索引,update 后重建)比方法 2(update 按顺序执行)执行行效率高 1 倍。

3.GreatSQL 源码分析
通过对 GreatSQL 源码的分析,了解到上面 update 语句从 server 层调用 InnoDB 存储引擎层函数的调用关系如下,每 update 1 行数据调用 ha_update_row () 一次,每 update 1 行数据后都要检查唯一索引是否发生冲突。

server层

Sql_cmd_update::update_single_table()
->ha_update_row() //更新一行数据
#innodb 存储引擎层
-> ha_innobase::update_row() //更新innodb一行数据
-> row_update_for_GreatSQL() //修改或删除数据
-> row_update_for_GreatSQL_using_upd_graph() //更新行
->row_upd_step() //更新行
->row_upd() //更新索引
->row_upd_sec_step() //更新索引
->row_ins_sec_index_entry() //向索引中插入记录
->row_ins_sec_index_entry_low() //向索引中插入记录
->row_ins_scan_sec_index_for_duplicate() //检查索引重复值
->row_ins_dupl_error_with_rec() //检查唯一索引冲突
handler::ha_update_row 函数的主要功能是更新表中的一行数据,并记录该操作到二进制日志中。
ha_innobase::update_row 函数的主要功能是更新 InnoDB 表中的一行数据。
row_update_for_GreatSQL 修改或删除数据行。
row_update_for_GreatSQL_using_upd_graph 函数的主要功能是处理 GreatSQL 的行更新操作。
row_upd_step 函数的主要功能是处理行更新操作。
row_upd 函数是更改数据行影响的索引。
row_upd_sec_step 函数是根据记录行的更改或删除,更改二级索引或删除二级索引。
row_ins_sec_index_entry 函数的主要功能是向二级索引中插入一条记录。
row_ins_sec_index_entry_low 函数的主要功能是向二级索引中插入一个索引项。它首先进行一些初始化和检查,然后根据索引类型(空间索引或普通索引)进行搜索。在搜索过程中,它会检查唯一性约束,并根据需要执行插入或修改操作。
row_ins_scan_sec_index_for_duplicate 函数的主要功能是扫描非聚集唯一索引,以检查是否存在与要插入的索引条目重复的记录。
row_ins_dupl_error_with_rec 函数的主要功能是检查在插入索引条目时是否会发生唯一键冲突。它通过比较要插入的条目和现有记录的字段来确定是否存在重复。
4. 总结
在更改唯一索引列时,Oracle 是完成 SQL 语句全部数据的更改后,再检查唯一索引的冲突;GreatSQL 则是在 SQL 语句更改每 1 条数据后,在更新索引数据检查唯一索引的冲突。在应用系统从 Oracle 迁移到 GreatSQL 时,需注意予以改写。

  1. 延伸阅读
    UPDATE 时主键冲突引发的思考 (https://imysql.com/2008_06_17_sth_about_update_duplicate_key)
    Enjoy GreatSQL

    标签:test1,GreatSQL,update,索引,Oracle,com,row
    From: https://www.cnblogs.com/XX-SHE/p/18537053

相关文章

  • Oracle 第28章:Oracle机器学习
    Oracle机器学习第28章:数据科学与机器学习基础及利用Oracle进行预测性分析在当今数据驱动的时代,数据科学和机器学习成为了企业决策的重要组成部分。Oracle作为一家领先的数据库技术提供商,不仅提供强大的数据库管理功能,还整合了先进的数据分析工具,使得用户能够轻松地在其环境......
  • Google 编入索引的文件类型
    Google可以将大多数文本文件和某些已编码文档格式的内容编入索引。最常编入索引的文件类型包括:Adobe便携式文档格式(.pdf)AdobePostScript(.ps)以逗号分隔的值(.csv)Google地球(.kml、.kmz)GPS交换格式(.gpx)HancomHanword(.hwp)HTML(.htm、.html、其他文件扩展名)Microso......
  • 2. MySQL 索引分类
    MySQL中的索引是提高数据查询速度的重要工具,就像一本书的目录,可以帮助我们快速定位到所需的内容。选择适合的索引类型对数据库设计和性能优化至关重要。本文将详细介绍MySQL中常见的索引类型,并重点讲解聚集索引和二级索引的概念及应用。1.主键索引(PrimaryKeyIndex)概......
  • Oracle 存储过程分页 + Sqlsugar调用
    一、Oracle存储过程分页1createPROCEDUREGetPatientVisitData(2p_HospIdINVARCHAR2,--院区编码3p_strDateINVARCHAR2,--开始日期4p_endDateINVARCHAR2,--结束日期5p_page_sizeINNUMBER,--每页记录数6p_page_numberIN......
  • 03 Oracle进程秘籍:深度解析Oracle后台进程体系
    文章目录Oracle进程秘籍:深度解析Oracle后台进程体系一、Oracle后台进程概览1.1DBWn(DatabaseWriterProcess)1.2LGWR(LogWriterProcess)1.3SMON(SystemMonitorProcess)1.4PMON(ProcessMonitorProcess)二、后台进程的监控与诊断2.1使用OracleEnterpriseManager(OE......
  • 04 深入 Oracle 并发世界:MVCC、锁、闩锁、事务隔离与并发性能优化的探索
    文章目录深入Oracle并发世界:MVCC、锁、闩锁、事务隔离与并发性能优化的探索一、多版本并发控制(MVCC)1.1理论解析1.2实践应用二、锁与闩锁机制2.1理论解析2.2实践应用三、事务隔离级别3.1理论解析3.2实践应用四、死锁预防与解决策略4.1理论解析4.2实践应用五......
  • Oracle OCP认证考试考点详解082系列15
    题记:本系列主要讲解OracleOCP认证考试考点(题目),适用于19C/21C,跟着学OCP考试必过。71.第71题:题目解析及答案:对于数据库,使用数据库配置助手(DBCA)可以执行以下哪两项任务?A.为新数据库配置非标准块大小。数据库配置助手(DBCA)可用于为新创建的数据库配置非标准块大小。在......
  • 【GreatSQL 优化器 - 01】const_table
    一、const_table介绍GreatSQL的优化器主要用JOIN类来进行处理SQL语句的,JOIN类有以下四个table数量相关的成员变量。其中const_tables是optimize最开始就检查并且标识的,因为这样可以把记录最少的表放在执行计划的第一步,在后面的执行计划里面这些consttables是不参......
  • 智谱BigModel研习社|搭建 AI 搜索引擎 - 使用免费的Web-Search-Pro+脑图Agent智能体
    作者:Cartman文章:多智能体AI搜索引擎点击链接,更多实践案例等你探索~ #智谱BigModel研习社是专业的大模型开发者交流平台,欢迎在评论区与我们互动! 传统搜索引擎如今的问题在于输出很多不相关结果(大量垃圾信息+SEO操纵的标题党内容),大模型也面临着幻觉问题。在网......
  • 【QOCI】【Oracle】qoci驱动编译
    文章目录前言一、安装QT、Oracle二、生成qsqloci.dll1.配置oci.pro2.修改qsqldriverbase.pri3.管理员身份运行x64NativeToolsCommandPromptforVS2022前言提示:qoci驱动配置很简单,参考网上失败,最后参照qt官网成功!一、安装QT、Oracle这里就不赘述了,其他教......