2014-10-08 70 views
1

我有2個Bash腳本通過目錄,從MP3中提取ID3信息並將它們導入到MySQL數據庫中。完成運行需要相當長的時間,所以我希望有人能夠幫助我使腳本更高效一些。加速Bash ID3到MySQL導入

腳本如下:

makeid3dbentry.sh

TRACK=$(id3info "$1" | grep '^=== TIT2' | sed -e 's/.*: //g') 
ARTIST=$(id3info "$1" | grep '^=== TPE1' | sed -e 's/.*: //g') 
ALBUM=$(id3info "$1" | grep '^=== TALB' | sed -e 's/.*: //g') 
ALBUMARTIST=$(id3info "$1" | grep '^=== TPE2' | sed -e 's/.*: //g') 

COLS='`artist`,`name`,`album`,`albumartist`,`filename`' 
# Replace all: ${string//substring/replacement} to escape " 
VALS='"'${ARTIST//\"/\\\"}'","'${TRACK//\"/\\\"}'","'${ALBUM//\"/\\\"}'","'${ALBUMARTIST//\"/\\\"}'","'${1}'"' 

SETLIST='`artist`="'${ARTIST//\"/\\\"}'",`name`="'${TRACK//\"/\\\"}'",`album`="'${ALBUM//\"/\\\"}'",`albumartist`="'${ALBUMARTIST//\"/\\\"}'",`filename`="'${1}'"' 

echo 'INSERT INTO `music` ('${COLS}') VALUES ('${VALS}') ON DUPLICATE KEY UPDATE '${SETLIST}';' 
exit 

產生的INSERT語句像

INSERT INTO `music` (`artist`,`name`,`album`,`albumartist`,`filename`) VALUES ("1200 Micrograms","Ayahuasca","1200 Micrograms","1200 Micrograms","/mnt/sharedmedia/music/Albums/1200 Micrograms/1200 Micrograms [2002]/1-01 - 1200 Micrograms - Ayahuasca.mp3") ON DUPLICATE KEY UPDATE `artist`="1200 Micrograms",`name`="Ayahuasca",`album`="1200 Micrograms",`albumartist`="1200 Micrograms",`filename`="/mnt/sharedmedia/music/Albums/1200 Micrograms/1200 Micrograms [2002]/1-01 - 1200 Micrograms - Ayahuasca.mp3"; 

接着從主更新腳本調用:

updatemusicdb.sh

DIRFULLPATH="${1}" 
DIRECTORY=$(basename "${DIRFULLPATH}") 

SQLFILE="/var/www/html/scripts/sql/rebuilddb_${DIRECTORY}.sql" 
find "${DIRFULLPATH}" -type f -iname "*.mp3" -exec /var/www/html/scripts/bash/makeid3dbentry.sh {} > "${SQLFILE}" \; 
mysql --defaults-extra-file=/var/www/html/config/website.cnf --default-character-set=utf8 "website" < "${SQLFILE}" 

不幸的是,我不知道Bash & Linux環境已經足以查看瓶頸在哪裏以及如何改進這些腳本。如果更好/更快,我將不勝感激任何有關改進腳本的建議,甚至還有其他方法。

+1

所有標籤的匹配AND輸出記錄的寫入可以在1 awk過程中完成。這種方式會更快。祝你好運。 – shellter 2014-10-08 21:02:40

回答

0

您可以避免按照評論中的建議多次運行id3info

您還可以使makeid3dbentry.sh在您的代碼周圍帶有一個簡單的for file in "${@}"多個參數。然後你可以運行find-exec yourscript.sh {} +(像xargs一樣工作)。這樣可以大大減少腳本的調用次數。不過,我可能會建議把這整個事情做成一個腳本。您可以使用find命令(不包含-exec參數)將插入語句生成包裝到for循環中,並將此輸出傳送到文件。

假設你的MySQL數據庫使用的是InnoDB,你可以通過告訴MySQL跳過提交數據直到作業完成(而不是每次插入)來加速插入。 將START TRANSACTION;插入到SQLFILE的頂部,並在底部插入COMMIT;。 請參閱http://dev.mysql.com/doc/refman/5.6/en/commit.htmlhttp://dev.mysql.com/doc/refman/5.5/en/optimizing-innodb-bulk-data-loading.html

+0

對不起,遲到接受。開始了一份新工作,這在混亂中迷失了方向。謝謝。 – 2015-03-20 10:34:19