ITPUB论坛-中国最专业的IT技术社区

 
 注册
热搜:
查看: 655|回复: 14

[SQL] oralce insert 大量数据 怎样更快

[复制链接]
求职 : 数据库开发
论坛徽章:
21
秀才
日期:2017-08-11 15:38:46秀才
日期:2018-01-02 15:13:25秀才
日期:2018-01-02 15:17:54秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22技术图书徽章
日期:2018-01-02 15:18:30秀才
日期:2018-01-02 15:05:41
跳转到指定楼层
1#
发表于 2018-1-4 12:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
是这样的 现在有一个几千万行的大表 想要每年把历史数据insert into 备份表  然后把前面的数据delete掉如果我想要这样的速度更快 我应该用什么方法

我先模拟一下insert 操作

DECLARE
    TYPE xx IS TABLE OF UROWID INDEX BY PLS_INTEGER;
    xxx xx;
    CURSOR y IS
        SELECT ROWID FROM bigtable ORDER BY ROWID;
BEGIN
    --EXECUTE IMMEDIATE 'CREATE TABLE all1 AS SELECT * FROM bigtable WHERE 1=2';
   -- EXECUTE IMMEDIATE 'CREATE TABLE all2 AS SELECT * FROM bigtable WHERE 1=2';
    timer.snap;
    INSERT INTO all1
        SELECT * FROM bigtable;
    COMMIT;
    timer.show('insert ...select...');
    timer.snap;
    OPEN y;
    LOOP
        FETCH y BULK COLLECT
            INTO xxx LIMIT 10000;
        EXIT WHEN xxx.count = 0;
        FORALL i IN 1 .. xxx.count
            INSERT INTO all2
                SELECT * FROM bigtable WHERE ROWID = xxx(i);
        COMMIT;
    END LOOP;
    CLOSE y;
    timer.show('rowid...forall...');
END;


当我把上面的语句执行两次之后
我发现
[insert ...select...] 261.00 seconds
[ORDER BY rowid...forall...] 1060.29 seconds
[insert ...select...] 138.37 seconds
[ORDER BY rowid...forall...] 1029.34 seconds


这个结果让我感到非常意外 为什么会这样       当然我知道我这个举例 肯定是 ctas 最快    但还有没有什么更好的方法么

第三次执行 CURSOR y IS
        SELECT ROWID FROM bigtable;    后面去掉了 ORDER BY ROWID
结果是
[insert ...select...] 144.31 seconds
[rowid...forall...] 1058.26 seconds



求职 : 数据库开发
论坛徽章:
21
秀才
日期:2017-08-11 15:38:46秀才
日期:2018-01-02 15:13:25秀才
日期:2018-01-02 15:17:54秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22技术图书徽章
日期:2018-01-02 15:18:30秀才
日期:2018-01-02 15:05:41
2#
 楼主| 发表于 2018-1-4 12:47 | 只看该作者
@newkid

使用道具 举报

回复
求职 : 数据库开发
论坛徽章:
21
秀才
日期:2017-08-11 15:38:46秀才
日期:2018-01-02 15:13:25秀才
日期:2018-01-02 15:17:54秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22技术图书徽章
日期:2018-01-02 15:18:30秀才
日期:2018-01-02 15:05:41
3#
 楼主| 发表于 2018-1-4 13:01 | 只看该作者
备份表没有索引和约束  原始表 是一个分区表  当然 delete之后 高水位线还是不会降低 但现在可以不用考虑这个

使用道具 举报

回复
求职 : 数据库开发
论坛徽章:
21
秀才
日期:2017-08-11 15:38:46秀才
日期:2018-01-02 15:13:25秀才
日期:2018-01-02 15:17:54秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22技术图书徽章
日期:2018-01-02 15:18:30秀才
日期:2018-01-02 15:05:41
4#
 楼主| 发表于 2018-1-4 17:30 | 只看该作者
本帖最后由 却早已分离 于 2018-1-4 18:09 编辑

大概知道为什么了 select大量数据 走索引反而更慢 ...
这种大量数据的 delete 也应该直接 delete where  是么



使用道具 举报

回复
认证徽章
论坛徽章:
0
5#
发表于 2018-1-4 21:22 | 只看该作者
却早已分离 发表于 2018-1-4 17:30
大概知道为什么了 select大量数据 走索引反而更慢 ...
这种大量数据的 delete 也应该直接 delete where   ...

你想一条一条Select 然后 Insert?
FORALL i IN 1 .. xxx.count
            INSERT INTO all2
                SELECT * FROM bigtable WHERE ROWID = xxx(i);

使用道具 举报

回复
求职 : 数据库开发
论坛徽章:
21
秀才
日期:2017-08-11 15:38:46秀才
日期:2018-01-02 15:13:25秀才
日期:2018-01-02 15:17:54秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22技术图书徽章
日期:2018-01-02 15:18:30秀才
日期:2018-01-02 15:05:41
6#
 楼主| 发表于 2018-1-4 21:27 | 只看该作者
本帖最后由 却早已分离 于 2018-1-4 21:28 编辑
Johnelse 发表于 2018-1-4 21:22
你想一条一条Select 然后 Insert?
FORALL i IN 1 .. xxx.count
            INSERT INTO all2

分页 10000行 commit 一次

使用道具 举报

回复
认证徽章
论坛徽章:
0
7#
发表于 2018-1-4 21:34 | 只看该作者
Johnelse 发表于 2018-1-4 21:22
你想一条一条Select 然后 Insert?
FORALL i IN 1 .. xxx.count
            INSERT INTO all2

两条语句搞定啊
1. insert into xxx select * from bigtable;
2. delete from bigtable where xxx;

使用道具 举报

回复
求职 : 数据库开发
论坛徽章:
21
秀才
日期:2017-08-11 15:38:46秀才
日期:2018-01-02 15:13:25秀才
日期:2018-01-02 15:17:54秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22秀才
日期:2018-01-02 15:18:22技术图书徽章
日期:2018-01-02 15:18:30秀才
日期:2018-01-02 15:05:41
8#
 楼主| 发表于 2018-1-4 22:10 | 只看该作者
Johnelse 发表于 2018-1-4 21:34
两条语句搞定啊
1. insert into xxx select * from bigtable;
2. delete from bigtable where xxx;

实际上我当然是有很多种方法搞定 只是在尝试之前 我没想到第二种方式会比第一种慢那么多 我以为会快的
第一种会堆满undo表空间

使用道具 举报

回复
论坛徽章:
6
生肖徽章2007版:鸡
日期:2008-01-02 17:35:532012新春纪念徽章
日期:2012-01-04 11:50:442011新春纪念徽章
日期:2011-01-04 10:35:17ITPUB十周年纪念徽章
日期:2011-11-01 16:20:28暖羊羊
日期:2015-03-04 14:50:372015年新春福章
日期:2015-03-06 11:57:31
9#
发表于 2018-1-4 23:12 | 只看该作者
大表和历史表都按照年分区。然后用交换分区互换一下就是,速度很快的。
来自安卓客户端来自客户端

使用道具 举报

回复
论坛徽章:
486
秀才
日期:2015-09-09 10:33:01秀才
日期:2015-11-23 10:03:12秀才
日期:2015-11-23 10:03:12状元
日期:2015-11-23 10:04:09举人
日期:2015-11-23 10:04:09秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21
10#
发表于 2018-1-5 00:29 | 只看该作者
这种需求就应该用分区表,越早改越好。
你顶楼的代码并没有用到索引,是直接用ROWID定位的,所以我看不懂你后面讲的SELECT走索引是什么意思。顶楼的例子可以去掉ORDER BY ROWID看看。

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档 |
  | | |
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 网站律师 隐私政策 知识产权声明
 北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表