copy part from 's3://<your-bucket-name>/load/part-csv.tbl'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>'
您可能會看到類似下列的錯誤訊息。
An error occurred when executing the SQL command:
copy part from 's3://amzn-s3-demo-bucket/load/part-csv.tbl'
credentials' ...
ERROR: Load into table 'part' failed. Check 'stl_load_errors' system table for details. [SQL State=XX000]
Execution time: 1.46s
1 statement(s) failed.
1 statement(s) failed.
若要取得有關錯誤的詳細資訊,請查詢 STL_LOAD_ERRORS 資料表。下列查詢使用 SUBSTRING 函數縮短資料欄以利閱讀,並使用 LIMIT 10 減少傳回的資料列數。您可以調整 substring(filename,22,25) 中的值,以符合您的儲存貯體名稱長度。
select query, substring(filename,22,25) as filename,line_number as line,
substring(colname,0,12) as column, type, position as pos, substring(raw_line,0,30) as line_text,
substring(raw_field_value,0,15) as field_text,
substring(err_reason,0,45) as reason
from stl_load_errors
order by query desc
limit 10;
query | filename | line | column | type | pos |
--------+-------------------------+-----------+------------+------------+-----+----
333765 | part-csv.tbl-000 | 1 | | | 0 |
line_text | field_text | reason
------------------+------------+----------------------------------------------
15,NUL next, | | Missing newline: Unexpected character 0x2c f
NULL AS
part-csv.tbl 資料檔案使用 NUL 結束字元 (\x000 或 \x0) 來指出 NULL 值。
雖然看起來很像,但 NUL 和 NULL 大不相同。NUL 是有 x000 字碼指標的 UTF-8 字元,通常用於表示記錄結束 (EOR)。NULL 是用來代表缺少某個值的 SQL 值。
根據預設,COPY 會將 NUL 結束字元視為 EOR 字元並終止記錄,而這常會造成未預期的結果或錯誤。指出文字資料中的 NULL 沒有任何單一的標準方法。因此,NULL AS COPY 命令選項可讓您指定在載入資料表時,要用哪個字元替換 NULL。在此範例中,要讓 COPY 將 NUL 結束字元當作 NULL 值。
必須將要接收 NULL 值的資料表欄設為 nullable。也就是說,在 CREATE TABLE 規格中,它一定不能包含 NOT NULL 限制。
若要使用 NULL AS 選項載入 PART,請執行以下 COPY 命令。
copy part from 's3://<your-bucket-name>/load/part-csv.tbl'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>'
null as '\000';
若要確認 COPY 已載入 NULL 值,執行下列命令可以僅選取包含 NULL 的資料列。
select p_partkey, p_name, p_mfgr, p_category from part where p_mfgr is null;
p_partkey | p_name | p_mfgr | p_category
-----------+----------+--------+------------
15 | NUL next | | MFGR#47
81 | NUL next | | MFGR#23
133 | NUL next | | MFGR#44
(2 rows)
DELIMITER 和 REGION 選項
DELIMITER 和 REGION 選項對於了解 如何載入資料至關重要。
字元分隔檔案中的欄位是以特殊字元隔開,例如縱線字元 ( | )、逗號 ( , ) 或 Tab 字元 ( \t )。字元分隔檔案可以使用任可單一 ASCII 字元做為分隔符號,包括其中一個非列印 ASCII 字元。請使用 DELIMITER 選項指定分隔符號。預設分隔符號是縱線字元 ( | )。
下列摘錄自 SUPPLIER 資料表的資料使用縱線分隔格式。
1|1|257368|465569|41365|19950218|2-HIGH|0|17|2608718|9783671|4|2504369|92072|2|19950331|TRUCK
1|2|257368|201928|8146|19950218|2-HIGH|0|36|6587676|9783671|9|5994785|109794|6|19950416|MAIL
REGION
您應該盡可能在與 Amazon Redshift 叢集相同的 AWS 區域中找到負載資料。如果您的資料和叢集位於相同區域中,可以降低延遲,並且避免跨區域傳輸資料的成本。如需詳細資訊,請參閱載入資料的 Amazon Redshift 最佳實務。
如果您必須從不同的 AWS 區域載入資料,請使用 REGION 選項來指定載入資料所在的 AWS 區域。如果指定區域,則所有載入資料 (包括資訊清單檔案) 都必須位於指定的區域。如需詳細資訊,請參閱REGION。
例如,如果您的叢集位於美國東部 (維吉尼亞北部) 區域,而您的 Amazon S3 儲存貯體位於美國西部 (奧勒岡) 區域,下列 COPY 命令會顯示如何從管道分隔資料載入 SUPPLIER 資料表。
copy supplier from 's3://amzn-s3-demo-bucket/ssb/supplier.tbl'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>'
delimiter '|'
region 'us-west-2';
使用 MANIFEST 載入 CUSTOMER 資料表
在此步驟中,您會使用 FIXEDWIDTH、MAXERROR、ACCEPTINVCHARS 和 MANIFEST 選項載入 CUSTOMER 資料表。
此練習的範例資料包含 COPY 嘗試載入時會造成錯誤的字元。您會使用 MAXERRORS 選項和 STL_LOAD_ERRORS 系統資料表,針對載入錯誤進行故障診斷,然後使用 ACCEPTINVCHARS 和 MANIFEST 選項消除錯誤。
固定寬度格式
固定寬度格式將每個欄位定義為固定數量的字元,而不是使用分隔符號分隔欄位。下列摘錄自 CUSTOMER 資料表的資料使用固定寬度格式。
1 Customer#000000001 IVhzIApeRb MOROCCO 0MOROCCO AFRICA 25-705
2 Customer#000000002 XSTf4,NCwDVaWNe6tE JORDAN 6JORDAN MIDDLE EAST 23-453
3 Customer#000000003 MG9kdTD ARGENTINA5ARGENTINAAMERICA 11-783
標籤/寬度配對的順序必須完全符合資料表欄的順序。如需詳細資訊,請參閱FIXEDWIDTH。
CUSTOMER 資料表固定寬度的規格字串如下。
fixedwidth 'c_custkey:10, c_name:25, c_address:25, c_city:10, c_nation:15,
c_region :12, c_phone:15,c_mktsegment:10'
若要從固定寬度資料載入 CUSTOMER 資料表,執行下列命令。
copy customer
from 's3://<your-bucket-name>/load/customer-fw.tbl'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>'
fixedwidth 'c_custkey:10, c_name:25, c_address:25, c_city:10, c_nation:15, c_region :12, c_phone:15,c_mktsegment:10';
您應該會看到類似下列的錯誤訊息。
An error occurred when executing the SQL command:
copy customer
from 's3://amzn-s3-demo-bucket/load/customer-fw.tbl'
credentials'...
ERROR: Load into table 'customer' failed. Check 'stl_load_errors' system table for details. [SQL State=XX000]
Execution time: 2.95s
1 statement(s) failed.
MAXERROR
根據預設,COPY 第一次遇到錯誤時,命令就會失敗並傳回錯誤訊息。若要在測試期間節省時間,您可以使用 MAXERROR 選項來指示 COPY 在失敗前可略過指定的錯誤數量。因為我們預料到第一次測試載入 CUSTOMER 資料表資料時會發生錯誤,請在 COPY 命令中加入 maxerror 10。
若要使用 FIXEDWIDTH 和 MAXERROR 選項進行測試,執行下列命令。
copy customer
from 's3://<your-bucket-name>/load/customer-fw.tbl'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>'
fixedwidth 'c_custkey:10, c_name:25, c_address:25, c_city:10, c_nation:15, c_region :12, c_phone:15,c_mktsegment:10'
maxerror 10;
這次,您不會看到錯誤訊息,而是得到類似下列的警示訊息。
Warnings:
Load into table 'customer' completed, 112497 record(s) loaded successfully.
Load into table 'customer' completed, 7 record(s) could not be loaded. Check 'stl_load_errors' system table for details.
警示表示 COPY 遇到 7 個錯誤。若要查看錯誤,請查詢 STL_LOAD_ERRORS 資料表,如以下範例所示。
select query, substring(filename,22,25) as filename,line_number as line,
substring(colname,0,12) as column, type, position as pos, substring(raw_line,0,30) as line_text,
substring(raw_field_value,0,15) as field_text,
substring(err_reason,0,45) as error_reason
from stl_load_errors
order by query desc, filename
limit 7;
查詢 STL_LOAD_ERRORS 的結果應如下所示。
query | filename | line | column | type | pos | line_text | field_text | error_reason
--------+---------------------------+------+-----------+------------+-----+-------------------------------+------------+----------------------------------------------
334489 | customer-fw.tbl.log | 2 | c_custkey | int4 | -1 | customer-fw.tbl | customer-f | Invalid digit, Value 'c', Pos 0, Type: Integ
334489 | customer-fw.tbl.log | 6 | c_custkey | int4 | -1 | Complete | Complete | Invalid digit, Value 'C', Pos 0, Type: Integ
334489 | customer-fw.tbl.log | 3 | c_custkey | int4 | -1 | #Total rows | #Total row | Invalid digit, Value '#', Pos 0, Type: Integ
334489 | customer-fw.tbl.log | 5 | c_custkey | int4 | -1 | #Status | #Status | Invalid digit, Value '#', Pos 0, Type: Integ
334489 | customer-fw.tbl.log | 1 | c_custkey | int4 | -1 | #Load file | #Load file | Invalid digit, Value '#', Pos 0, Type: Integ
334489 | customer-fw.tbl000 | 1 | c_address | varchar | 34 | 1 Customer#000000001 | .Mayag.ezR | String contains invalid or unsupported UTF8
334489 | customer-fw.tbl000 | 1 | c_address | varchar | 34 | 1 Customer#000000001 | .Mayag.ezR | String contains invalid or unsupported UTF8
(7 rows)
檢查結果時,您可以看到 error_reasons 資料欄中有兩則訊息:
Invalid digit, Value '#', Pos 0, Type: Integ
這些錯誤是由 customer-fw.tbl.log 檔案引起。問題在於,它是日誌檔案不是資料檔案,不應載入它。您可以使用資訊清單檔案來避免載入錯誤的檔案。
String contains invalid or unsupported UTF8
VARCHAR 資料類型支援最多 3 個位元組的 UTF-8 多位元組字元。如果載入資料包含不支援或無效的字元,您可以使用 ACCEPTINVCHARS 選項用指定的替代字元取代每個無效字元。
另一個載入的問題比較難偵測 — 載入產生非預期的結果。若要調查這個問題,執行下列命令查詢 CUSTOMER 資料表。
select c_custkey, c_name, c_address
from customer
order by c_custkey
limit 10;
c_custkey | c_name | c_address
-----------+---------------------------+---------------------------
2 | Customer#000000002 | XSTf4,NCwDVaWNe6tE
2 | Customer#000000002 | XSTf4,NCwDVaWNe6tE
3 | Customer#000000003 | MG9kdTD
3 | Customer#000000003 | MG9kdTD
4 | Customer#000000004 | XxVSJsL
4 | Customer#000000004 | XxVSJsL
5 | Customer#000000005 | KvpyuHCplrB84WgAi
5 | Customer#000000005 | KvpyuHCplrB84WgAi
6 | Customer#000000006 | sKZz0CsnMD7mp4Xd0YrBvx
6 | Customer#000000006 | sKZz0CsnMD7mp4Xd0YrBvx
(10 rows)
這些資料列應該是獨一無二的,但其中有重複。
另一個檢查非預期結果的方法,是去確有已載入的資料列數量。在我們的案例中,應該載入 100000 列資料,但載入訊息指出載入 112497 個記錄。會載入多的資料列,是因為 COPY 載入無關的檔案 customer-fw.tbl0000.bak。
在這個練習中,您會使用資訊清單檔案來避免載入錯誤的檔案。
ACCEPTINVCHARS
根據預設,當 COPY 遇到欄位資料類型不支援的字元,會略過該資料列並傳回錯誤。如需無效 UTF-8 字元的相關資訊,請參閱多位元組字元載入錯誤。
您可以使用 MAXERRORS 選項來略過錯誤並繼續載入,然後查詢 STL_LOAD_ERRORS 來找出無效字元,接著修正資料檔案。不過,MAXERRORS 最好用於進行載入問題的故障診斷,不應廣泛使用在生產環境中。
ACCEPTINVCHARS 選項通常是管理無效字元更好的選擇。ACCEPTINVCHARS 選項會指示 COPY 用指定的有效字元取代每個無效字元,並繼續載入操作。您可以指定 NULL 除外的任何 ASCII 字元做為替代字元。預設的替代字元是問號 ( ? )。COPY 會將多位元組字元取代為相等長度的替代字元。例如,4 個位元組的字元會被取代為 '????'。
COPY 會傳回包含無效 UTF-8 字元的資料列數。其也會將項目新增至每個受影響資料列的 STL_REPLACEMENTS 系統資料表,每個節點分割最多 100 個資料列。也會取代其他無效 UTF-8 字元,但不會記錄那些取代事件。
ACCEPTINVCHARS 僅適用於 VARCHAR 欄。
您會在此步驟中使用替代字元 '^' 新增 ACCEPTINVCHARS。
MANIFEST
當您使用金鑰前綴從 Amazon S3 COPY 時,其中一個風險是您可能會載入不必要的資料表。例如,'s3://amzn-s3-demo-bucket/load/ 資料夾包含 8 個檔案,它們有相同的索引鍵字首 customer-fw.tbl:customer-fw.tbl0000、customer-fw.tbl0001 等。然而,同一資料夾中也包含無關的檔案 customer-fw.tbl.log 和 customer-fw.tbl-0001.bak。
為了確保載入所有正確的檔案,且只有正確的檔案,請使用資訊清單檔案。資訊清單是 JSON 格式的文字檔案,其中明確列出要載入之每個來源檔案的唯一物件索引鍵。檔案物件可以位於不同的資料夾或儲存貯體,但必須在同一個區域中。如需詳細資訊,請參閱MANIFEST。
以下顯示 customer-fw-manifest 的文字。
"entries": [
{"url":"s3://<your-bucket-name>/load/customer-fw.tbl-000"},
{"url":"s3://<your-bucket-name>/load/customer-fw.tbl-001"},
{"url":"s3://<your-bucket-name>/load/customer-fw.tbl-002"},
{"url":"s3://<your-bucket-name>/load/customer-fw.tbl-003"},
{"url":"s3://<your-bucket-name>/load/customer-fw.tbl-004"},
{"url":"s3://<your-bucket-name>/load/customer-fw.tbl-005"},
{"url":"s3://<your-bucket-name>/load/customer-fw.tbl-006"},
{"url":"s3://<your-bucket-name>/load/customer-fw.tbl-007"}
使用資訊清單檔案從 CUSTOMER 資料表載入資料
-
在文字編輯器中開啟 customer-fw-manifest 檔案。
以您的儲存貯體名稱取代 <your-bucket-name>。
儲存檔案。
將檔案上傳到儲存貯體上的 load 資料夾。
執行下列 COPY 命令。
copy customer from 's3://<your-bucket-name>/load/customer-fw-manifest'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>'
fixedwidth 'c_custkey:10, c_name:25, c_address:25, c_city:10, c_nation:15, c_region :12, c_phone:15,c_mktsegment:10'
maxerror 10
acceptinvchars as '^'
manifest;
在此步驟中,您會使用 DELIMITER 和 DATEFORMAT 選項載入 DWDATE 資料表。
載入 DATE 和 TIMESTAMP 資料欄時,COPY 期望是預設格式:日期為 YYYY-MM-DD,時間戳記為 YYYY-MM-DD HH:MI:SS。如果載入的資料不是使用預設格式,您可以使用 DATEFORMAT 和 TIMEFORMAT 指定格式。
下列的摘錄顯示了 DWDATE 資料表中的日期格式。注意兩個資料欄的日期格式不一致。
19920104 1992-01-04 Sunday January 1992 199201 Jan1992 1 4 4 1...
19920112 January 12, 1992 Monday January 1992 199201 Jan1992 2 12 12 1...
19920120 January 20, 1992 Tuesday January 1992 199201 Jan1992 3 20 20 1...
您只能指定一個日期格式。如果載入資料包含不一致的格式 (可能在不同資料欄中),或是載入時格式未知,請使用 DATEFORMAT 與 'auto' 引數。指定 'auto' 時,COPY 會辨識所有有效的日期或時間格式,並將其轉換為預設格式。'auto' 選項可以辨識使用 DATEFORMAT 和 TIMEFORMAT 字串時不支援的多種格式。如需詳細資訊,請參閱對 DATEFORMAT 和 TIMEFORMAT 使用自動辨識。
若要載入 DWDATE 資料表,執行下列 COPY 命令。
copy dwdate from 's3://<your-bucket-name>/load/dwdate-tab.tbl'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>'
delimiter '\t'
dateformat 'auto';
載入多個資料檔案
您可以使用 GZIP 和 COMPUPDATE 選項來載入資料表。
您可以從單一資料檔案或多個檔案載入資料表。執行此操作來比較這兩種方法的載入時間。
GZIP、LZOP 與 BZIP2
您可以使用 gzip、lzop 或 bzip2 壓縮格式來壓縮您的檔案。從解壓縮檔案載入時,COPY 會在載入程序中將檔案解壓縮。將檔案壓縮可以節省儲存空間及縮短載入時間。
COMPUPDATE
當 COPY 載入無壓縮編碼的空資料表時,會分析載入資料並決定最佳的編碼。接著它會將資料表修改為使用這些編碼,再開始載入。這個分析程序需要一點時間,但幾乎在每個資料表都會發生一次。若要節省時報,您可以關閉 COMPUPDATE 來略過這個步驟。為了準確評估 COPY 時間,您會在這個步驟中關閉 COMPUPDATE。
相較於從單一檔案載入資料,COPY 命令從多個檔案平行載入資料更有效率。您可以將您的資料分割為檔案,使得檔案的數量為您叢集中配量數量的倍數。若您執行此作業,Amazon Redshift 會分割工作負載,並在配量中平均分配資料。每一節點的配量數目取決於叢集的節點大小。如需每個節點大小有多少配量的相關資訊,請參閱《Amazon Redshift 管理指南》中的關於叢集和節點。
例如,本教學課程中叢集中的運算節點每個可以有兩個配量,因此四節點叢集有八個配量。先前的步驟將載入的資料分成八個檔案,即使檔案很小。您可以比較從單一大型檔案載入和從多個檔案載入之間的時間差異。
即使是包含 1,500 萬筆記錄且佔用約 1.2 GB 的檔案,Amazon Redshift 規模也非常小。但它們足以示範從多個檔案載入的效能優勢。
下圖顯示 LINEORDER 的資料檔案。
評估 COPY 多個檔案的效能
-
在實驗室測試中,從單一檔案對 COPY 執行下列命令。此命令會顯示虛構的儲存貯體。
copy lineorder from 's3://amzn-s3-demo-bucket/load/lo/lineorder-single.tbl'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>'
compupdate off
region 'us-east-1';
結果如下。請注意執行時間。
Warnings:
Load into table 'lineorder' completed, 14996734 record(s) loaded successfully.
0 row(s) affected.
copy executed successfully
Execution time: 51.56s
然後,從多個檔案對 COPY 執行下列命令。
copy lineorder from 's3://amzn-s3-demo-bucket/load/lo/lineorder-multi.tbl'
credentials 'aws_iam_role=arn:aws:iam::<aws-account-id>:role/<role-name>'
compupdate off
region 'us-east-1';
結果如下。請注意執行時間。
Warnings:
Load into table 'lineorder' completed, 14996734 record(s) loaded successfully.
0 row(s) affected.
copy executed successfully
Execution time: 17.7s
比較執行時間。
在我們的實驗中,載入 1,500 萬筆記錄的時間從 51.56 秒縮短為 17.7 秒,減少了 65.7%。
這些結果來自於使用具有四個節點的叢集。如果您的叢集有更多節點,節省的時間會加倍。典型的 Amazon Redshift 叢集有數十到數百個節點,差別更巨大。如果您的叢集只有單一節點,執行時間的差異很小。
每當您新增、刪除或修改大量資料列時,應先後執行 VACUUM 命令及 ANALYZE 命令。vacuum (清空) 會恢復已刪除資料列的空間,並還原排序。ANALYZE 命令會更新統計中繼資料,後者可讓查詢最佳化工具產生更正確的查詢計畫。如需詳細資訊,請參閱清空資料表。
如果您以排序索引鍵的順序載入資料,清空很快。在本教學課程中,您已新增大量資料列,但是將它們新增到空資料表。在這種情況下,不需要重新排序,您也沒有刪除任何資料列。COPY 會在載入空資料表後自動更新統計,因此您的統計應該是最新的。但基於良好的內務處理,您會清空並分析資料庫以完成本教學。
若要清空並分析資料庫,執行下列命令。
vacuum;
analyze;
步驟 7:清理您的資源
叢集只要執行就會繼續產生費用。完成本教學課程後,您應按照 Amazon Redshift 入門指南中的步驟 5:撤銷存取權並刪除範例叢集中的步驟,將環境恢復到先前的狀態。
如果您要保留叢集,但又想復原 SSB 資料表所使用的儲存體,請執行下列命令。
drop table part;
drop table supplier;
drop table customer;
drop table dwdate;
drop table lineorder;
Summary
Summary
在本教學課程中,您已將檔案上傳到 Amazon S3,並使用 COPY 命令將資料從該檔案載入 Amazon Redshift 資料表。
您已使用以下格式載入資料:
您已使用 STL_LOAD_ERRORS 系統資料表進行載入錯誤的故障診斷,並使用 REGION、MANIFEST、MAXERROR、ACCEPTINVCHARS、DATEFORMAT、NULL AS 選項解決錯誤。
您已運用下列最佳實務來載入資料: