2017-02-14 128 views
1

我有一個Java應用程序,從一組表中讀取,處理數據,然後將處理的數據插入到一個表中。數據量真的很大,多線程是不可避免的。 當多個線程嘗試同時插入時會發生問題,這會導致寫入保持和插入保持。之後,所有線程等待表可用,直到連接超時。插入多線程插入到Redshift表導致鎖

  • 的記錄沒有任何外鍵指向插入

  • 記錄的所有表都完全相互獨立的

  • 該表中沒有的增量ID任何一種

  • 沒有其他應用程序正在使用的任何本申請中涉及的表

我正在使用Java準備語句來執行插入操作。每個調用一個插入方法,分別爲每個線程打開一個連接。

有什麼我做錯了,或者它是與Redshift的兼容性問題?

+0

您使用連接池嗎?爭論可能是因爲我認爲數據倉庫產品能夠處理上面概述的情況(儘管我對Redshift沒有特別的瞭解) – DaveH

+0

根據文檔:COPY和INSERT操作是純粹的寫入...針對同一個表的COPY和INSERT操作保持等待狀態,直到釋放鎖,然後它們照常進行。請參閱http://docs.aws.amazon.com/es_es/redshift/latest/ dg/c_write_readwrite.html –

+0

但基於此,這意味着線程進入隊列以執行插入操作。但是非線程正在插入。 –

回答

2

將大量的小插入到單個連接的Redshift表格中肯定是not what you want to doRedshift WLM query queues不適合許多小型併發操作。默認情況下,只有5個查詢將同時運行,並且您希望將這些查詢保存爲實際的工作查詢,而不是loading。當您認爲Redshift針對超大型數據集上的少量長時間運行查詢進行了優化時,這是有意義的。

對於你的情況,我建議你看看使用Kinesis Firehoseload your data into Redshift。它專門爲此目的而設計,您可以從多個線程高效寫入。它會batch the data for you,可以給你一個機會,如果需要過濾/轉換數據,並有副作用備份到S3如果需要的話。

這是Java example

+0

我似乎無法找到一種方法來通過java來做到這一點。因爲複製命令依賴於文件,所以請按照這裏的文檔[鏈接](http://docs.aws.amazon.com/redshift/latest/dg/r_COPY。html) –

+0

如果你想直接從S3加載文件而不是像上面最後一個鏈接那樣使用Kinesis,Java不需要知道S3,它只需要在Redshift上運行的COPY命令中指定S3路徑。 Redshift將使用COPY中提供的憑據從S3本身獲取文件。下面是一個示例COPY命令:'COPY your_table FROM's3://your_bucket/path/file.csv.gz'CREDENTIALS'aws_access_key_id = yourkey; aws_secret_access_key = yoursecret'DELIMITER','NULL'NULL'IGNOREBLANKLINES EMPTYASNULL BLANKSASNULL TIMEFORMAT'auto' FILLRECORD MAXERROR 1 CSV GZIP'。 – systemjack

+0

不,我的意思是沒有辦法使用copy命令直接從Java插入,而不必從文件中插入。 –