关于一个oracle下遇到的insert into ...select... 效率很慢的问题

通过调整执行计划提升含有子查询的复杂SELECT语句的执行效率。

先描述一下问题前提条件是select语句本身执行并不慢,我一个select查询,单独执行的话大约7秒左右,可能算是有些复杂,然后前面加上insert into去执行的话,刚开始的时候还好,后面越来越慢,最后遥遥无期看不到头,问题比较困扰,网上搜到一个帖子,地址:http://www.itpub.net/thread-1599007-1-1.html,在第二页中有位用户提到在select中增加/*+ no_merge(p) use_hash(p) */这样的方式,看了一下我的语句和这个情况还是比较相似的,试了一下还真管用,效率显而易见。

 

简单描述一下场景和用法:在select语句的from子句中有一个子查询,类似于select t_1.a,t_3.b from t_1,(select c,d from t_2) t_3,然后这么用,加上上面说的那段,把语句改成:

select /*+ no_merge(t_3) use_hash(t_3) */ t_1.a,t_3.b from t_1,(select c,d from t_2) t_3 where t_3.xx=t1.xx,括号里的就是from子句中的子查询所给的命名。

具体的语句比这复杂,要不然也不应该会这么慢,作用大概是修改oracle默认的执行计划,具体的还不清楚,这里先把问题解决了,关于no_merge和use_hash的作用慢慢琢磨吧。

<think>我们正在讨论数据库操作中的INSERT INTO语句,特别是单条和多条数据插入的方法。根据用户的问题,用户希望了解如何执行单条和多条INSERT语句来新增数据。 根据提供的引用,我们可以总结出以下几种插入数据的方法: 1. 单条插入:使用INSERT INTO ... VALUES ... 语句插入一行数据。 2. 多条插入(方法1):使用INSERT INTO ... VALUES ... 后跟多个用逗号分隔的值列表,一次性插入多行数据(如引用[3]所示)。 3. 多条插入(方法2):使用INSERT INTO ... SELECT ... UNION ALL ... 的方式,通过查询结果插入多行数据(如引用[1]所示)。 4. 多条插入(方法3):使用INSERT INTO ... SELECT ... 从另一个表中选择数据插入(如引用[1]所示)。 下面我们将详细说明这些方法。 ### 单条数据插入 单条插入是最基本的形式,语法如下: ```sql INSERT INTO 表名 (列1, 列2, 列3, ...) VALUES (值1, 值2, 值3, ...); ``` 例如,向`user_info`表中插入一条用户信息: ```sql INSERT INTO user_info (user_account, user_name, user_age, user_class) VALUES ('00001', '张三', 20, '计算机系'); ``` ### 多条数据插入 如果需要一次性插入多条数据,可以使用以下方法: #### 方法1:使用单个INSERT语句和多个VALUES子句(推荐) 这是最常用的多条插入方法,语法如下: ```sql INSERT INTO 表名 (列1, 列2, 列3, ...) VALUES (值1a, 值2a, 值3a, ...), (值1b, 值2b, 值3b, ...), ...; ``` 例如,向`user_info`表中插入三条记录: ```sql INSERT INTO user_info (user_account, user_name, user_age, user_class) VALUES ('00001', '张三', 20, '计算机系'), ('00002', '李四', 19, '计算机系'), ('00003', '王五', 21, '数学系'); ``` 这种方法在大多数数据库系统(如MySQL, SQL Server, PostgreSQL等)中都支持,且效率较高。 #### 方法2:使用UNION ALL结合SELECT 这种方法适用于一些不支持上述多条插入语法的数据库(如旧版本的SQL Server),或者需要从其他表或表达式中构造数据的情况。语法如下: ```sql INSERT INTO 表名 (列1, 列2, 列3, ...) SELECT 值1a, 值2a, 值3a, ... UNION ALL SELECT 值1b, 值2b, 值3b, ... UNION ALL ... ``` 例如: ```sql INSERT INTO user_info (user_account, user_name, user_age, user_class) SELECT '00001', '张三', 20, '计算机系' UNION ALL SELECT '00002', '李四', 19, '计算机系' UNION ALL SELECT '00003', '王五', 21, '数学系'; ``` 注意:这种方法在插入大量数据时性能可能不如方法1,因为每个SELECT UNION ALL都会被视为一个单独的查询,然后合并。 #### 方法3:从另一个表中选择数据插入 如果数据已经存在于另一个表中,可以使用INSERT INTO ... SELECT ... 语句。例如: ```sql INSERT INTO user_info (user_account, user_name, user_age, user_class) SELECT account, name, age, class FROM temp_user; ``` 这里,`temp_user`是另一个表,我们从中选取数据插入到`user_info`表中。 ### 注意事项 1. 列的顺序和数量必须与VALUES子句中的值顺序和数量一致。 2. 如果省略列名,则VALUES子句中必须提供表中所有列的值,且顺序与表定义一致。 3. 插入时需注意数据类型匹配和约束(如主键唯一性、非空约束等)。 ### 总结 根据实际需求选择插入方式: - 单条插入:适用于插入单条记录。 - 多条插入(方法1):适用于一次性插入多条记录,简洁高效。 - 多条插入(方法2):在特定情况下使用,如旧版本数据库或不支持方法1的情况。 - 从其他表插入:适用于数据迁移或复制。 希望这些方法能帮助您高效地完成数据插入操作。 §§相关问题§§ 1. 在插入多条数据时,如果有一条数据插入失败,会发生什么? 2. 如何提高大批量数据插入的性能? 3. 不同数据库(如MySQL、SQL Server、Oracle)在插入多条数据时的语法差异?</think>### 数据库 INSERT INTO VALUES 单条与多条数据插入方法 #### 一、单条数据插入 语法格式: ```sql INSERT INTO 表名 (字段1, 字段2, ...) VALUES (值1, 值2, ...); ``` **示例**: ```sql -- 插入单条用户数据 INSERT INTO user_info (user_account, user_name, user_age) VALUES ('U1001', '张三', 25); ``` > 特点:每次执行仅插入一行数据,适合零星数据操作[^1]。 #### 二、多条数据插入 ##### 方法1:VALUES 多值列表(推荐) ```sql INSERT INTO 表名 (字段1, 字段2, ...) VALUES (值1a, 值2a, ...), (值1b, 值2b, ...), ...; ``` **示例**: ```sql -- 一次性插入3条学生记录 INSERT INTO students (stu_id, name, major) VALUES ('S2023', '李四', '计算机'), ('S2024', '王五', '数学'), ('S2025', '赵六', '物理'); ``` > ✅ 优势:单条SQL完成批量插入,效率最高[^3]。 ##### 方法2:UNION ALL 联合查询 ```sql INSERT INTO 表名 (字段1, 字段2, ...) SELECT '值1a', '值2a' UNION ALL SELECT '值1b', '值2b' UNION ALL ...; ``` **示例**: ```sql -- 插入多门课程信息 INSERT INTO courses (course_id, course_name) SELECT 'C101', '数据库' UNION ALL SELECT 'C102', '算法' UNION ALL SELECT 'C103', '网络'; ``` > ⚠️ 注意:适用于旧版数据库(如SQL Server 2000)[^1]。 ##### 方法3:从其他表复制数据 ```sql INSERT INTO 目标表 (字段1, 字段2, ...) SELECT 字段1, 字段2, ... FROM 源表 WHERE 条件; ``` **示例**: ```sql -- 从临时表导入数据 INSERT INTO employees (emp_id, dept) SELECT temp_id, department FROM temp_hire WHERE status = 'approved'; ``` ### 关键注意事项 1. **字段顺序**:VALUES中的值顺序必须与字段声明顺序一致 2. **省略字段**:若省略字段列表,需提供所有字段值(含自增ID) 3. **性能对比**: - 插入100行数据时,多值列表比单条插入快10倍以上 - UNION ALL方式会有额外解析开销 4. **事务控制**: ```sql BEGIN TRANSACTION; INSERT INTO ... -- 批量操作 COMMIT; -- 确保原子性 ``` ### 不同数据库语法差异 | 数据库 | 多值列表支持 | 最大单次插入行数 | |--------------|--------------|------------------| | MySQL 8.0 | ✅ | 受max_allowed_packet限制 | | SQL Server | ✅ | 1000(建议分批) | | PostgreSQL | ✅ | 无硬性限制 | | Oracle 12c+ | ✅ | 1000(推荐BULK INSERT)| > 实际开发中优先使用多值列表法,兼顾效率与可读性[^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值