MySQL データベース (InnoDB エンジン) にインポートされている、約 400 GB の大量のプレーン テキスト ファイルのセットがあります (私が考えていること)。.txt ファイルのサイズは 2GB から 26GB で、各ファイルはデータベース内のテーブルを表します。.txt ファイルを解析して SQL ステートメントを作成する Python スクリプトが与えられました。私は、次の仕様のこのタスク専用のマシンを持っています。
- OS - Windows 10
- 32GBのRAM
- 4TBのハードドライブ
- i7 3.40 GHz プロセッサー
このインポートを最適化して、可能な限り迅速かつダーティにしたいと考えています。スタック O の質問、MySQL ドキュメント、およびその他のソースに基づいて、MySQL my.ini ファイルの次の構成設定を変更しました。
max_allowed_packet=1073741824;
autocommit=0;
net_buffer_length=0;
foreign_key_check=0;
unique_checks=0;
innodb_buffer_pool_size=8G; (this made a big difference in speed when I increased from the default of 128M)
マシンのリソースのかなりの部分を使用するように MySQL に指示する、私が見逃した構成ファイルの他の設定 (ログやキャッシュに関するものかもしれません) はありますか? 私が見逃している別のボトルネックはありますか?
(サイドノート: これが関連しているかどうかはわかりません - インポートを開始すると、mysqldプロセスがスピンアップしてシステムのメモリの約 13-15% を使用しますが、Python スクリプトがインポートを続行するのを停止すると、プロセスは決してパージされないようです。 . これはログとフラッシュの設定をいじった結果なのだろうか. 事前に助けてくれてありがとう.)
(編集)
テーブルにデータを入力する Python スクリプトの関連部分を次に示します。スクリプトは、50,000 レコードごとに接続、コミット、および接続を閉じているようです。関数の最後にあるを削除してconn.commit()、MySQL にコミットを処理させることはできますか? 以下のコメントwhile (true)はスクリプトの作成者からのもので、max_allowed_packet サイズを超えないようにその数を調整しました。
conn = self.connect()
while (True):
#By default, we concatenate 200 inserts into a single INSERT statement.
#a large batch size per insert improves performance, until you start hitting max_packet_size issues.
#If you increase MySQL server's max_packet_size, you may get increased performance by increasing maxNum
records = self.parser.nextRecords(maxNum=50000)
if (not records):
break
escapedRecords = self._escapeRecords(records) #This will sanitize the records
stringList = ["(%s)" % (", ".join(aRecord)) for aRecord in escapedRecords]
cur = conn.cursor()
colVals = unicode(", ".join(stringList), 'utf-8')
exStr = exStrTemplate % (commandString, ignoreString, tableName, colNamesStr, colVals)
#unquote NULLs
exStr = exStr.replace("'NULL'", "NULL")
exStr = exStr.replace("'null'", "NULL")
try:
cur.execute(exStr)
except MySQLdb.Warning, e:
LOGGER.warning(str(e))
except MySQLdb.IntegrityError, e:
#This is likely a primary key constraint violation; should only be hit if skipKeyViolators is False
LOGGER.error("Error %d: %s", e.args[0], e.args[1])
self.lastRecordIngested = self.parser.latestRecordNum
recCheck = self._checkProgress()
if recCheck:
LOGGER.info("...at record %i...", recCheck)
conn.commit()
conn.close()