欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Oracle批量投入數(shù)據(jù)方法總結(jié)

 更新時(shí)間:2025年01月14日 10:32:26   作者:fengyehongWorld  
這篇文章主要介紹了Oracle批量投入數(shù)據(jù)方法總結(jié),文中通過代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有的一定的幫助,需要的朋友可以參考下

零. 待投入數(shù)據(jù)的表結(jié)構(gòu)

create table DB_USER."PERSON_TABLE" (
  ID NUMBER not null
  , NAME VARCHAR2(50)
  , AGE NUMBER
  , EMAIL VARCHAR2(100)
  , CREATED_DATE DATE
)

一. INSERT INTO ... SELECT投入數(shù)據(jù)

 INSERT INTO ... SELECT的這種方式相當(dāng)于把數(shù)據(jù)加載到內(nèi)存中之后再插入數(shù)據(jù)庫(kù),只適合投入小規(guī)模的數(shù)據(jù)。

1.1 普通的方式投入數(shù)據(jù)

當(dāng)數(shù)據(jù)量不是很多的時(shí)候,可以使用這種方式

  • 先從DUAL虛擬表中檢索后造出指定條數(shù)的數(shù)據(jù)后,再插入到指定的表中。
  • 除了主鍵之類的關(guān)鍵字段之外,其余字段寫固定值即可。
INSERT INTO PERSON_TABLE
	SELECT
		-- 因?yàn)樵撟侄螢樽址问?所以使用TO_CHAR轉(zhuǎn)換
		-- TO_CHAR(100000000 + LEVEL) || 'TEST_ID' AS id,
		LEVEL AS id,
		'Name_' || ROWNUM AS name,
        TRUNC(DBMS_RANDOM.VALUE(18, 60)) AS age,
        'user' || ROWNUM || '@example.com' AS email,
        SYSDATE - DBMS_RANDOM.VALUE(0, 365) AS created_date
	FROM
		DUAL 
	CONNECT BY LEVEL <= 1000000;

1.2 并行插入(Parallel Insert)投入數(shù)據(jù)

ALTER SESSION ENABLE PARALLEL DML;
INSERT /*+ PARALLEL(PERSON_TABLE, 4) */ INTO PERSON_TABLE
SELECT LEVEL AS id,
       'Name_' || ROWNUM AS name,
       TRUNC(DBMS_RANDOM.VALUE(18, 60)) AS age,
       'user' || ROWNUM || '@example.com' AS email,
       SYSDATE - DBMS_RANDOM.VALUE(0, 365) AS created_date
FROM DUAL
CONNECT BY LEVEL <= 1000000;

二. PL/SQL 循環(huán)投入數(shù)據(jù)

2.1 腳本介紹

  • 靈活,支持動(dòng)態(tài)生成數(shù)據(jù),適合中小數(shù)據(jù)量。
  • 數(shù)據(jù)量大時(shí)性能較差,容易導(dǎo)致上下文切換開銷。
BEGIN
    FOR i IN 1..5000000 LOOP
        INSERT INTO PERSON_TABLE (id, name, age, email, created_date)
        VALUES (
            i,
            'Name_' || i,
            -- 隨機(jī)年齡
            TRUNC(DBMS_RANDOM.VALUE(18, 60)),
            'user' || i || '@example.com',
            -- 隨機(jī)日期
            SYSDATE - DBMS_RANDOM.VALUE(0, 365)
        );

        -- 每 100000 條提交一次
        IF MOD(i, 100000) = 0 THEN
            COMMIT;
        END IF;
        
    END LOOP;
    
    COMMIT;
END;
/

2.2 效果

投入500萬條數(shù)據(jù),耗時(shí)5分鐘。

三. PL/SQL FORALL 批量操作

3.1 腳本介紹

  • 這種方式可以減少上下文切換,性能比普通的循環(huán)插入要好。
DECLARE
    TYPE person_array IS TABLE OF PERSON_TABLE%ROWTYPE;
    v_data person_array := person_array();
BEGIN
    FOR i IN 1..5000000 LOOP
        v_data.EXTEND;
        v_data(v_data.COUNT).id := i;
        v_data(v_data.COUNT).name := 'Name_' || i;
        v_data(v_data.COUNT).age := TRUNC(DBMS_RANDOM.VALUE(18, 60));
        v_data(v_data.COUNT).email := 'user' || i || '@example.com';
        v_data(v_data.COUNT).created_date := SYSDATE - DBMS_RANDOM.VALUE(0, 365);

        -- 每 100000 條批量插入一次
        IF MOD(i, 100000) = 0 THEN
            FORALL j IN 1..v_data.COUNT
                INSERT INTO PERSON_TABLE VALUES v_data(j);
            COMMIT;
            v_data.DELETE; -- 清空數(shù)組
        END IF;
    END LOOP;

    -- 插入剩余數(shù)據(jù)
    FORALL j IN 1..v_data.COUNT
        INSERT INTO PERSON_TABLE VALUES v_data(j);
    COMMIT;
END;
/

3.2 效果

投入500萬條數(shù)據(jù),耗時(shí)1分鐘18秒。

四. SQL*Loader 工具加載外部文件

寫一個(gè)PowerShell腳本,根據(jù)數(shù)據(jù)庫(kù)的表結(jié)構(gòu)來生成csv文件

  • 該腳本執(zhí)行后,會(huì)在桌面上生成一個(gè)csv文件。
# 文件名稱
$file_name = 'person_data.csv'
# 路徑
$outputFile = "$Home\Desktop\$file_name"
# csv 文件的總行數(shù)
$rows = 5000000
# 并行線程數(shù)
$threadCount = 4
# 每個(gè)線程生成的記錄數(shù)量
$chunkSize = [math]::Ceiling($rows / $threadCount)

# 判斷文件是否存在,存在的話就刪除
if (Test-Path -Path $outputFile) {
    Remove-Item -Path $outputFile -Force
}

# 寫入 CSV 表頭
# "`"ID`",`"NAME`",`"AGE`",`"EMAIL`",`"CREATED_DATE`"" | Out-File -FilePath $outputFile -Encoding UTF8 -Append

# 定義腳本塊
$scriptblock = {
    
    param($startRow, $endRow, $tempFile)

    # 在后臺(tái)作業(yè)中定義 Generate-Chunk 函數(shù)
    function Generate-Chunk {
        
        param (
            [int]$startRow,
            [int]$endRow,
            [string]$filePath
        )

        $random = [System.Random]::new()
        $currentDate = Get-Date
        $sb = [System.Text.StringBuilder]::new()

		# 循環(huán)生成csv數(shù)據(jù)
        for ($i = $startRow; $i -le $endRow; $i++) {
			
			# =========================對(duì)應(yīng)數(shù)據(jù)庫(kù)的各字段值=========================
            $id = $i
            $name = "Name_$i"
            $age = $random.Next(18, 60)
            $email = "user$i@example.com"
            $createdDate = $currentDate.AddDays(- $random.Next(0, 365)).ToString("yyyy/MM/dd HH:mm:ss")
            # =========================對(duì)應(yīng)數(shù)據(jù)庫(kù)的各字段值=========================
			
			# =========================一行csv=========================
            $line = "`"$id`",`"$name`",`"$age`",`"$email`",`"$createdDate`""
            # =========================一行csv=========================

            $sb.AppendLine($line) | Out-Null
        }

        <# 
            將生成的內(nèi)容寫入文件
            -NoNewline 的作用是為了防止csv文件的最后一行被追加空行
        #>
        $sb.ToString() | Out-File -FilePath $filePath -Encoding UTF8 -Append -NoNewline
    }

    # 調(diào)用 Generate-Chunk 函數(shù),多線程生成臨時(shí)csv文件
    Generate-Chunk -startRow $startRow -endRow $endRow -filePath $tempFile
}

# CSV文件合成
function Merge-CSV {
        
	param (
		[string]$outputFile,
		[bool]$IsReadAllDataToMemory
	)
	
	# 獲取所有分段文件,按名稱排序
    $partFiles = Get-ChildItem -Path "$outputFile.*.part" | Sort-Object Name
	
	if ($IsReadAllDataToMemory) {
		
		# 將所有內(nèi)容加載到內(nèi)存中,然后一次性寫入
		$partFiles | ForEach-Object { Get-Content $_.FullName } | Out-File -FilePath $outputFile -Encoding UTF8 -Force
		# 刪除所有分段文件
		$partFiles | ForEach-Object { Remove-Item $_.FullName }
		
		return;
	}
	
	$partFiles | ForEach-Object {
        Get-Content -Path $_.FullName | Out-File -FilePath $outputFile -Encoding UTF8 -Append
        Remove-Item -Path $_.FullName
    }
}
    
try {
	# 定義job數(shù)組
    $jobs = @()
	
	# 組裝job
    1..$threadCount | ForEach-Object {
		
        $startRow = ($_ - 1) * $chunkSize + 1
        $endRow = [math]::Min($_ * $chunkSize, $rows)
		
		# 臨時(shí)csv文件
        $tempFile = "$outputFile.$_.part"

        $jobs += Start-Job -ScriptBlock $scriptblock -ArgumentList $startRow, $endRow, $tempFile
    }
	
	# 統(tǒng)計(jì)生成csv文件所消耗的時(shí)間
    $exec_time = Measure-Command {

        Write-Host "臨時(shí)csv文件開始生成..."

        # 執(zhí)行job,等待并收集所有執(zhí)行結(jié)果
        $jobs | ForEach-Object { Wait-Job -Job $_; Receive-Job -Job $_; Remove-Job -Job $_ }

        # 合并所有并發(fā)生成的csv臨時(shí)文件,組裝成最終的總csv文件
        Write-Host "臨時(shí)csv文件生成完畢,開啟合并..."
        Merge-CSV -outputFile $outputFile -IsReadAllDataToMemory $False
    }

    Write-Host "csv文件生成完畢,共消耗$($exec_time.TotalSeconds)秒: $outputFile" -ForegroundColor Red
	
} catch {

    # 當(dāng)異常發(fā)生時(shí),清空桌面上的臨時(shí)csv文件
    if (Test-Path -Path "$outputFile.*.part") {
        Remove-Item -Path "$outputFile.*.part" -Force
    }

    Write-Host "腳本運(yùn)行時(shí)發(fā)生異常: $_" -ForegroundColor Red
    Write-Host "詳細(xì)信息: $($_.Exception.Message)" -ForegroundColor Yellow
    Write-Host "堆棧跟蹤: $($_.Exception.StackTrace)" -ForegroundColor Gray
}

Read-Host "按 Enter 鍵退出..."

創(chuàng)建控制文件control_file.ctl

LOAD DATA
INFILE 'person_data.csv'
INTO TABLE PERSON_TABLE
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
(id, name, age, email, created_date "TO_DATE(:created_date, 'YYYY/MM/DD HH24:MI:SS')")

使用 SQL*Loader 執(zhí)行加載

  • 性能極高,適合大規(guī)模數(shù)據(jù)插入。
  • 支持多線程和并行加載。
sqlldr db_user/oracle@SERVICE_XEPDB1_CLIENT control=control_file.ctl direct=true

4.1 效果

投入500萬條數(shù)據(jù),耗時(shí)居然不到10秒!

到此這篇關(guān)于Oracle批量投入數(shù)據(jù)方法總結(jié)的文章就介紹到這了,更多相關(guān)Oracle投入數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • ORACLE11g隨RHEL5系統(tǒng)自動(dòng)啟動(dòng)與關(guān)閉的設(shè)置方法

    ORACLE11g隨RHEL5系統(tǒng)自動(dòng)啟動(dòng)與關(guān)閉的設(shè)置方法

    最近,ORACLE系統(tǒng)基本調(diào)試通過,是時(shí)候設(shè)置ORACLE隨RHEL自動(dòng)啟動(dòng)與關(guān)閉服務(wù)的時(shí)候了,之所以把這個(gè)任務(wù)放在最后來做,是因?yàn)槲矣X得這個(gè)應(yīng)該不會(huì)很難,但真正實(shí)施起來,還是遇到了個(gè)不小的障礙
    2009-08-08
  • Oracle中字符串截取常用方法總結(jié)【推薦】

    Oracle中字符串截取常用方法總結(jié)【推薦】

    這篇文章主要介紹了Oracle中字符串截取常用方法總結(jié),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-11-11
  • 淺析Oracle中sys、system和Scott用戶下的數(shù)據(jù)庫(kù)連接問題

    淺析Oracle中sys、system和Scott用戶下的數(shù)據(jù)庫(kù)連接問題

    這篇文章主要介紹了關(guān)于Oracle中sys、system和Scott用戶下的數(shù)據(jù)庫(kù)連接問題,本文通過示例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-07-07
  • oracle去除字符串中制表符、換行、回車及空格方法代碼

    oracle去除字符串中制表符、換行、回車及空格方法代碼

    在Oracle數(shù)據(jù)庫(kù)中有時(shí)我們需要處理字符串中的特殊字符,下面這篇文章主要給大家介紹了關(guān)于oracle去除字符串中制表符、換行、回車及空格的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • 解決PL/SQL修改Oracle存儲(chǔ)過程編譯就卡死的問題

    解決PL/SQL修改Oracle存儲(chǔ)過程編譯就卡死的問題

    這篇文章主要介紹了PL/SQL修改Oracle存儲(chǔ)過程編譯就卡死,本文給大家分享問題原因及解決方法,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • 理解和使用Oracle 8i分析工具LogMiner

    理解和使用Oracle 8i分析工具LogMiner

    理解和使用Oracle 8i分析工具LogMiner...
    2007-03-03
  • Oracle數(shù)據(jù)庫(kù)執(zhí)行計(jì)劃的查看與分析技巧

    Oracle數(shù)據(jù)庫(kù)執(zhí)行計(jì)劃的查看與分析技巧

    在 Oracle 數(shù)據(jù)庫(kù)中,執(zhí)行計(jì)劃能夠幫助我們深入了解 SQL 語句在數(shù)據(jù)庫(kù)內(nèi)部的執(zhí)行細(xì)節(jié),進(jìn)而優(yōu)化查詢性能、提升系統(tǒng)效率,執(zhí)行計(jì)劃是 Oracle 數(shù)據(jù)庫(kù)優(yōu)化器為 SQL 語句生成的一種執(zhí)行藍(lán)圖,本文給大家介紹了Oracle數(shù)據(jù)庫(kù)執(zhí)行計(jì)劃的查看與分析技巧,需要的朋友可以參考下
    2024-12-12
  • Oracle中3種常用的分頁查詢方法

    Oracle中3種常用的分頁查詢方法

    這篇文章主要給大家介紹了關(guān)于Oracle中3種常用的分頁查詢方法,分頁查詢就是把query到的結(jié)果集按頁顯示,比如一個(gè)結(jié)果集有1W行,每頁按100條數(shù)據(jù)庫(kù),而你獲取了第2頁的結(jié)果集,需要的朋友可以參考下
    2023-09-09
  • oracle索引的測(cè)試實(shí)例代碼

    oracle索引的測(cè)試實(shí)例代碼

    這篇文章主要給大家介紹了關(guān)于oracle索引測(cè)試的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Oracle用戶自定義異常實(shí)現(xiàn)過程解析

    Oracle用戶自定義異常實(shí)現(xiàn)過程解析

    這篇文章主要介紹了Oracle用戶自定義異常實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09

最新評(píng)論