SQLSERVER大批量數據快速導入Redis


目的

把單表近5千萬的某單個字段導入到Redis,作為一個list存儲。

方案一: 使用sqlcmd工具(sqlserver自帶),直接生成命令在Redis-cli中執行。

方案一. 使用sqlcmd把打印結果輸出在文本中,然后用redis-cli逐行執行文本中的命令。

redis寫入list的命令。

LPUSH openids xxxx
  1. 用sqlserver拼接處這個結果
SET NOCOUNT ON;
SELECT 'LPUSH openids ' +'"' + openID +'"'
 FROM [dbo].[table1] 

  1. 使用sqlcmd,推送到redis-cli執行
# -S:服務器地址,-U:賬號名 -P:密碼 -d:數據庫 -h:列標題之間打印的行數
sqlcmd -S . -U sa -P xxxx -d DataImport -h -1 -i d:\openid.sql | redis-cli -h 192.168.xx.xx -a xxxx -p 6379 

結論

  1. 能勉強成功。
  2. 導入速度慢,大概2w/s ~ 3w/s。遠低於Redis的寫入理想值。
  3. 容易出錯,如果value中含有意外字符,會導致命令執行失敗,結束任務。
  4. 別用這個方法。

官網支撐:

Redis is a TCP server using the client-server model and what is called a Request/Response protocol.

This means that usually a request is accomplished with the following steps:

The client sends a query to the server, and reads from the socket, usually in a blocking way, for the server response.
The server processes the command and sends the response back to the client.

方案二: 使用sqlcmd工具(sqlserver自帶),直接生成redis協議在Redis-cli中執行。(可以直接看這個方案)

使用sqlserver直接生成協議命令

--*3:由三個參數組成:LPUSH,key,value。
--$5: 'LPUSH'的字符串長度。
--$7: 'openids'的字符串長度。
--$n: {value}的長度
--char(13): /r
--char(10): /n
SET NOCOUNT ON;
SELECT '*3'+char(13)+CHAR(10) + '$5'+char(13)+CHAR(10) + 'LPUSH'+char(13)+CHAR(10) + '$7'+char(13)+CHAR(10)
 + 'openids'+char(13)+CHAR(10) +'$'+ CAST(DATALENGTH(openID) as varchar(255)) +char(13)+CHAR(10)+openID+char(13)+CHAR(10)
FROM [dbo].[table1] 

image

# --pipe 使用管道模式
sqlcmd -S . -U sa -P xxxx -d DataImport -h -1 -i d:\openid.sql | redis-cli -h 192.168.xx.xx -a xxxx -p 6379  --pipe

執行效果:

(為什么只有2660萬條呢?因為我分兩次運行了)

結論:

  1. 不會受value的影響,中斷運行。
  2. 運行速度快,差不多13w/s。接近理想值。
  3. 親測,第一次在寫入2800萬的時候,我的128G內存撐不住了,Redis直接崩了。所以,我選擇rownumber() over()從中斷的地方,繼續寫入。

官網支撐:

Using a normal Redis client to perform mass insertion is not a good idea for a few reasons: the naive approach of sending one command after the other is slow because you have to pay for the round trip time for every command. It is possible to use pipelining, but for mass insertion of many records you need to write new commands while you read replies at the same time to make sure you are inserting as fast as possible.

Only a small percentage of clients support non-blocking I/O, and not all the clients are able to parse the replies in an efficient way in order to maximize throughput. For all this reasons the preferred way to mass import data into Redis is to generate a text file containing the Redis protocol, in raw format, in order to call the commands needed to insert the required data.

附:

# sqlcmd導出到文本
sqlcmd -S . -U sa -P xxx -d DataImport -h -1 -i d:\openid.sql > d:\tt.txt
# 從文本推到redis-cli執行。
type protocol-commands.txt | redis-cli -h 192.168.xx.xx -a xxxx -p 6379 --pipe

把redis的正常命令轉成協議格式的批處理腳本

親測,近5千萬數據的文本,是動都動不了。

while read CMD; do
  # each command begins with *{number arguments in command}\r\nW
  XS=($CMD); printf "*${#XS[@]}\r\n"WWW
  # for each argument, we append ${length}\r\n{argument}\r\n
  for X in $CMD; do printf "\$${#X}\r\n$X\r\n"; done
done < origin-commands.txt

協議樣本:

*3
$5
LPUSH
$3
arr
$4
AAAA

*3
$5
LPUSH
$3
arr
$4
BBBB


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM