CSV ファイルインポートとは:CSVファイルをリレーショナルデータベースのテーブルにインポートする.
このページで紹介しているソフトウエア類の利用条件等は,利用者で確認すること.
SQLite 3 のインストールと利用の入門: 別ページにまとめている.
PostgreSQL の詳細は 別ページにまとめている.
次のように設定して実行すること.
エラーメッセージが出ないことを確認.
# インポートのプログラム cat >import.sql<<EOF .separator , pragma journal_mode=off; .import T1000M_1.csv T1000M_1 .exit EOF # クリーンアップ(clean up) echo -n > t1000m_1.db rm -f t1000m_1.db # インポート(import) cat import.sql | time sqlite3 t1000m_1.db rm -f import.sql # 問い合わせ(query) echo "select * from T1000M_1 limit 10;" | sqlite3 t1000m_1.db echo "select region, count(*) from T1000M_1 group by region;" | sqlite3 t1000m_1.db echo "select birth_cap from T1000M_1 where birth_cap > 80000 limit 10;" | sqlite3 t1000m_1.db
その性能計測
次のプログラムを実行(dstat を用いて性能を見る)
# キャッシュのクリア(PageCache, dentries and inodes) function cache_clear() { /usr/bin/sync /usr/bin/sync /usr/bin/sync /usr/bin/sync /usr/bin/sync sleep 3 sudo sysctl -w vm.drop_caches=3 > /dev/null echo 3 | sudo tee -a /proc/sys/vm/drop_caches > /dev/null return } # 性能を見たいプログラム,上のプログラムと同じ cat >import.sql<<EOF .separator , pragma journal_mode=off; .import T1000M_1.csv T1000M_1 .exit EOF # クリーンアップ(clean up),上のプログラムと同じ echo -n > t1000m_1.db rm -f t1000m_1.db # dstat データをプロットするプログラムの準備 WIDTH=48 HEIGHT=20 sudo apt -y install dstat rm -f dstatplot.py wget https://www.kkaneko.jp/data/rdb/dstatplot.py # キャッシュのクリア cache_clear # 48 のところは表示の横幅 # 20 のところは表示の縦幅 # 表示が始まるまで「表示の横幅」秒待つこと. dstat -tcdylm -C 0,1,2,3,4,5,6,7 | python3 dstatplot.py $WIDTH $HEIGHT & sleep $WIDTH # インポート(import),上のプログラムと同じ cat import.sql | time sqlite3 t1000m_1.db rm -f import.sql
数字 0 から 7 はプロセッサのコア.R, W はストレージの読み書き.m はメモリ使用量
前半は CPU バウンド(ディスク読み込みは余裕がある),後半は I/O バウンド(今度はプロセッサは余裕がある)ように読み取ることができる.
次のように設定して実行すること.
# インポートのプログラム cat >import.sql<<EOF truncate T1000M_1; copy T1000M_1 from '`pwd`/T1000M_1.csv' with csv header; \q EOF # クリーンアップ(clean up) echo "drop database if exists testdb" | sudo -u postgres psql -U postgres sudo service postgresql stop sudo rm -rf /var/lib/postgresql/data sudo mkdir /var/lib/postgresql/data sudo chown -R postgres:postgres /var/lib/postgresql/data sudo -u postgres /usr/lib/postgresql/12/bin/initdb --encoding=UTF-8 --locale=ja_JP.UTF8 -D /var/lib/postgresql/data > /dev/null sudo service postgresql start echo "create database testdb owner postgres encoding 'UTF8';" | sudo -u postgres psql -U postgres # インポート(import) cat T1000M_1.sql | sudo -u postgres psql -U postgres -d testdb cat import.sql | sudo -u postgres time psql -U postgres -d testdb --single-transaction rm -f import.sql # 問い合わせ(query) echo "select * from T1000M_1 limit 10;" | sudo -u postgres psql -U postgres -d testdb echo "select region, count(*) from T1000M_1 group by region;" | sudo -u postgres psql -U postgres -d testdb echo "select birth_cap from T1000M_1 where birth_cap > 80000 limit 10;" | sudo -u postgres psql -U postgres -d testdb
その性能計測
次のプログラムを実行(dstat を用いて性能を見る)
# キャッシュのクリア(PageCache, dentries and inodes) function cache_clear() { /usr/bin/sync /usr/bin/sync /usr/bin/sync /usr/bin/sync /usr/bin/sync sleep 3 sudo sysctl -w vm.drop_caches=3 > /dev/null echo 3 | sudo tee -a /proc/sys/vm/drop_caches > /dev/null return } # 性能を見たいプログラム,上のプログラムと同じ cat >import.sql<<EOF truncate T1000M_1; copy T1000M_1 from '`pwd`/T1000M_1.csv' with csv header; \q EOF # クリーンアップ(clean up),上のプログラムと同じ echo "drop database if exists testdb" | sudo -u postgres psql -U postgres sudo service postgresql stop sudo rm -rf /var/lib/postgresql/data sudo mkdir /var/lib/postgresql/data sudo chown -R postgres:postgres /var/lib/postgresql/data sudo -u postgres /usr/lib/postgresql/12/bin/initdb --encoding=UTF-8 --locale=ja_JP.UTF8 -D /var/lib/postgresql/data sudo service postgresql start echo "create database testdb owner postgres encoding 'UTF8';" | sudo -u postgres psql -U postgres # dstat データをプロットするプログラムの準備 WIDTH=48 HEIGHT=20 sudo apt -y install dstat rm -f dstatplot.py wget https://www.kkaneko.jp/data/rdb/dstatplot.py # キャッシュのクリア cache_clear # 48 のところは表示の横幅 # 20 のところは表示の縦幅 # 表示が始まるまで「表示の横幅」秒待つこと. dstat -tcdylm -C 0,1,2,3,4,5,6,7 | python3 dstatplot.py $WIDTH $HEIGHT & sleep $WIDTH # インポート(import),上のプログラムと同じ cat T1000M_1.sql | sudo -u postgres psql -U postgres -d testdb --single-transaction cat import.sql | sudo -u postgres time psql -U postgres -d testdb rm -f import.sql
数字 0 から 7 はプロセッサのコア.R, W はストレージの読み書き.m はメモリ使用量
リード,ライトが直ちに始まる.そして,読み込まれたデータはメモリ上に残る. メモリは直ちには開放されない.なお,トランザクション終了後に,データの書き込みが行われる.
#/bin/bash function elapsed() { echo `python3 -c "import sys; print( float(sys.argv[2]) - float(sys.argv[1]) )" $1 $2` return } function avg() { echo `python3 -c 'import sys; print("%.3f" % ((float(sys.argv[1]) + float(sys.argv[2]) + float(sys.argv[3])) / 3.0) )' $1 $2 $3` return } # キャッシュのクリア(PageCache, dentries and inodes) function cache_clear() { /usr/bin/sync /usr/bin/sync /usr/bin/sync /usr/bin/sync /usr/bin/sync sleep 3 sudo sysctl -w vm.drop_caches=3 > /dev/null echo 3 | sudo tee -a /proc/sys/vm/drop_caches > /dev/null return } function file_clean_up() { echo -n > $1 rm -f $1 } # $1: CSV file name, $2: Table name, $3: SQLite3 Database name function sqlite3_import() { # クリーンアップ(clean up) echo -n > $3 rm -f $3 rm -f sqlite3_import.sql # インポートのプログラム cat >sqlite3_import.sql<<EOF .separator , pragma journal_mode=off; .import $1 $2 .exit EOF start=`date +%s.%N` cat sqlite3_import.sql | sqlite3 $3 > /dev/null current=`date +%s.%N` echo `elapsed $start $current` return } # 250M cache_clear elapsed1=`sqlite3_import T250M_1.csv T250M_1 t250m_1.db` file_clean_up t250m_1.db cache_clear elapsed2=`sqlite3_import T250M_1.csv T250M_1 t250m_1.db` file_clean_up t250m_1.db cache_clear elapsed3=`sqlite3_import T250M_1.csv T250M_1 t250m_1.db` file_clean_up t250m_1.db echo 250M: `avg $elapsed1 $elapsed2 $elapsed3` # 500M cache_clear elapsed1=`sqlite3_import T500M_1.csv T500M_1 t500m_1.db` file_clean_up t500m_1.db cache_clear elapsed2=`sqlite3_import T500M_1.csv T500M_1 t500m_1.db` file_clean_up t500m_1.db cache_clear elapsed3=`sqlite3_import T500M_1.csv T500M_1 t500m_1.db` file_clean_up t500m_1.db echo 500M: `avg $elapsed1 $elapsed2 $elapsed3` # 1000M cache_clear elapsed1=`sqlite3_import T1000M_1.csv T1000M_1 t1000m_1.db` file_clean_up t1000m_1.db cache_clear elapsed2=`sqlite3_import T1000M_1.csv T1000M_1 t1000m_1.db` file_clean_up t1000m_1.db cache_clear elapsed3=`sqlite3_import T1000M_1.csv T1000M_1 t1000m_1.db` file_clean_up t1000m_1.db echo 1000M: `avg $elapsed1 $elapsed2 $elapsed3` # 2000M cache_clear elapsed1=`sqlite3_import T2000M_1.csv T2000M_1 t2000m_1.db` file_clean_up t2000m_1.db cache_clear elapsed2=`sqlite3_import T2000M_1.csv T2000M_1 t2000m_1.db` file_clean_up t2000m_1.db cache_clear elapsed3=`sqlite3_import T2000M_1.csv T2000M_1 t2000m_1.db` file_clean_up t2000m_1.db echo 2000M: `avg $elapsed1 $elapsed2 $elapsed3` # 4000M cache_clear elapsed1=`sqlite3_import T4000M_1.csv T4000M_1 t4000m_1.db` file_clean_up t4000m_1.db cache_clear elapsed2=`sqlite3_import T4000M_1.csv T4000M_1 t4000m_1.db` file_clean_up t4000m_1.db cache_clear elapsed3=`sqlite3_import T4000M_1.csv T4000M_1 t4000m_1.db` file_clean_up t4000m_1.db echo 4000M: `avg $elapsed1 $elapsed2 $elapsed3` # 8000M cache_clear elapsed1=`sqlite3_import T8000M_1.csv T8000M_1 t8000m_1.db` file_clean_up t8000m_1.db cache_clear elapsed2=`sqlite3_import T8000M_1.csv T8000M_1 t8000m_1.db` file_clean_up t8000m_1.db cache_clear elapsed3=`sqlite3_import T8000M_1.csv T8000M_1 t8000m_1.db` file_clean_up t8000m_1.db echo 8000M: `avg $elapsed1 $elapsed2 $elapsed3` # 12000M cache_clear elapsed1=`sqlite3_import T12000M_1.csv T12000M_1 t12000m_1.db` file_clean_up t12000m_1.db cache_clear elapsed2=`sqlite3_import T12000M_1.csv T12000M_1 t12000m_1.db` file_clean_up t12000m_1.db cache_clear elapsed3=`sqlite3_import T12000M_1.csv T12000M_1 t12000m_1.db` file_clean_up t12000m_1.db echo 12000M: `avg $elapsed1 $elapsed2 $elapsed3` # 16000M cache_clear elapsed1=`sqlite3_import T16000M_1.csv T16000M_1 t16000m_1.db` file_clean_up t16000m_1.db cache_clear elapsed2=`sqlite3_import T16000M_1.csv T16000M_1 t16000m_1.db` file_clean_up t16000m_1.db cache_clear elapsed3=`sqlite3_import T16000M_1.csv T16000M_1 t16000m_1.db` file_clean_up t16000m_1.db echo 16000M: `avg $elapsed1 $elapsed2 $elapsed3` # 20000M cache_clear elapsed1=`sqlite3_import T20000M_1.csv T20000M_1 t20000m_1.db` file_clean_up t20000m_1.db cache_clear elapsed2=`sqlite3_import T20000M_1.csv T20000M_1 t20000m_1.db` file_clean_up t20000m_1.db cache_clear elapsed3=`sqlite3_import T20000M_1.csv T20000M_1 t20000m_1.db` file_clean_up t20000m_1.db echo 20000M: `avg $elapsed1 $elapsed2 $elapsed3` # 24000M cache_clear elapsed1=`sqlite3_import T24000M_1.csv T24000M_1 t24000m_1.db` file_clean_up t24000m_1.db cache_clear elapsed2=`sqlite3_import T24000M_1.csv T24000M_1 t24000m_1.db` file_clean_up t24000m_1.db cache_clear elapsed3=`sqlite3_import T24000M_1.csv T24000M_1 t24000m_1.db` file_clean_up t24000m_1.db echo 24000M: `avg $elapsed1 $elapsed2 $elapsed3` # 28000M cache_clear elapsed1=`sqlite3_import T28000M_1.csv T28000M_1 t28000m_1.db` file_clean_up t28000m_1.db cache_clear elapsed2=`sqlite3_import T28000M_1.csv T28000M_1 t28000m_1.db` file_clean_up t28000m_1.db cache_clear elapsed3=`sqlite3_import T28000M_1.csv T28000M_1 t28000m_1.db` file_clean_up t28000m_1.db echo 28000M: `avg $elapsed1 $elapsed2 $elapsed3` # 32000M cache_clear elapsed1=`sqlite3_import T32000M_1.csv T32000M_1 t32000m_1.db` file_clean_up t32000m_1.db cache_clear elapsed2=`sqlite3_import T32000M_1.csv T32000M_1 t32000m_1.db` file_clean_up t32000m_1.db cache_clear elapsed3=`sqlite3_import T32000M_1.csv T32000M_1 t32000m_1.db` file_clean_up t32000m_1.db echo 32000M: `avg $elapsed1 $elapsed2 $elapsed3` # 36000M cache_clear elapsed1=`sqlite3_import T36000M_1.csv T36000M_1 t36000m_1.db` file_clean_up t36000m_1.db cache_clear elapsed2=`sqlite3_import T36000M_1.csv T36000M_1 t36000m_1.db` file_clean_up t36000m_1.db cache_clear elapsed3=`sqlite3_import T36000M_1.csv T36000M_1 t36000m_1.db` file_clean_up t36000m_1.db echo 36000M: `avg $elapsed1 $elapsed2 $elapsed3` # 40000M cache_clear elapsed1=`sqlite3_import T40000M_1.csv T40000M_1 t40000m_1.db` file_clean_up t40000m_1.db cache_clear elapsed2=`sqlite3_import T40000M_1.csv T40000M_1 t40000m_1.db` file_clean_up t40000m_1.db cache_clear elapsed3=`sqlite3_import T40000M_1.csv T40000M_1 t40000m_1.db` file_clean_up t40000m_1.db echo 40000M: `avg $elapsed1 $elapsed2 $elapsed3`
#/bin/bash function elapsed() { echo `python3 -c "import sys; print( float(sys.argv[2]) - float(sys.argv[1]) )" $1 $2` return } function avg() { echo `python3 -c 'import sys; print("%.3f" % ((float(sys.argv[1]) + float(sys.argv[2]) + float(sys.argv[3])) / 3.0) )' $1 $2 $3` return } # キャッシュのクリア(PageCache, dentries and inodes) function cache_clear() { /usr/bin/sync /usr/bin/sync /usr/bin/sync /usr/bin/sync /usr/bin/sync sleep 3 sudo sysctl -w vm.drop_caches=3 > /dev/null echo 3 | sudo tee -a /proc/sys/vm/drop_caches > /dev/null return } F=/etc/postgresql/12/main/postgresql.conf function archive_mode_on() { sudo sed -i 's/#wal_level = minimal/wal_level = minimal/g' $F sudo sed -i 's/#wal_level = replica/wal_level = minimal/g' $F sudo sed -i 's/wal_level = replica/wal_level = minimal/g' $F sudo sed -i 's/#wal_level = logical/wal_level = minimal/g' $F sudo sed -i 's/wal_level = logical/wal_level = minimal/g' $F } function archive_mode_off() { sudo sed -i 's/#wal_level = minimal/wal_level = replica/g' $F sudo sed -i 's/wal_level = minimal/wal_level = replica/g' $F sudo sed -i 's/#wal_level = replica/wal_level = replica/g' $F sudo sed -i 's/#wal_level = logical/wal_level = replica/g' $F sudo sed -i 's/wal_level = logical/wal_level = replica/g' $F } # $1: CSV file name, $2: Table name, $3: PostgreSQL Database name function psql_import() { # クリーンアップ(clean up) echo "drop database if exists $3" | sudo -u postgres psql -U postgres > /dev/null cache_clear sudo service postgresql stop cache_clear sudo rm -rf /var/lib/postgresql/data sudo mkdir /var/lib/postgresql/data sudo chown -R postgres:postgres /var/lib/postgresql/data sudo -u postgres /usr/lib/postgresql/12/bin/initdb --encoding=UTF-8 --locale=ja_JP.UTF8 -D /var/lib/postgresql/data > /dev/null sudo service postgresql start echo "create database $3 owner postgres encoding 'UTF8';" | sudo -u postgres psql -U postgres 1>/dev/null 2>/dev/null # cat $4 | sudo -u postgres psql -U postgres -d $3 > /dev/null rm -f psql_import.sql # インポートのプログラム cat >psql_import.sql<<EOF truncate $2; copy $2 from '`pwd`/$1' with csv header; \q EOF start=`date +%s.%N` cat psql_import.sql | sudo -u postgres time psql -U postgres -d $3 --single-transaction --quiet 1>/dev/null 2>/dev/null current=`date +%s.%N` echo `elapsed $start $current` return } # archive_mode_off # 250M cache_clear elapsed1=`psql_import T250M_1.csv T250M_1 t250m_1_db T250M_1.sql` cache_clear elapsed2=`psql_import T250M_1.csv T250M_1 t250m_1_db T250M_1.sql` cache_clear elapsed3=`psql_import T250M_1.csv T250M_1 t250m_1_db T250M_1.sql` echo 250M: `avg $elapsed1 $elapsed2 $elapsed3` # 500M cache_clear elapsed1=`psql_import T500M_1.csv T500M_1 t500m_1_db T500M_1.sql` cache_clear elapsed2=`psql_import T500M_1.csv T500M_1 t500m_1_db T500M_1.sql` cache_clear elapsed3=`psql_import T500M_1.csv T500M_1 t500m_1_db T500M_1.sql` echo 500M: `avg $elapsed1 $elapsed2 $elapsed3` # 1000M cache_clear elapsed1=`psql_import T1000M_1.csv T1000M_1 t1000m_1_db T1000M_1.sql` cache_clear elapsed2=`psql_import T1000M_1.csv T1000M_1 t1000m_1_db T1000M_1.sql` cache_clear elapsed3=`psql_import T1000M_1.csv T1000M_1 t1000m_1_db T1000M_1.sql` echo 1000M: `avg $elapsed1 $elapsed2 $elapsed3` # 2000M cache_clear elapsed1=`psql_import T2000M_1.csv T2000M_1 t2000m_1_db T2000M_1.sql` cache_clear elapsed2=`psql_import T2000M_1.csv T2000M_1 t2000m_1_db T2000M_1.sql` cache_clear elapsed3=`psql_import T2000M_1.csv T2000M_1 t2000m_1_db T2000M_1.sql` echo 2000M: `avg $elapsed1 $elapsed2 $elapsed3` # 4000M cache_clear elapsed1=`psql_import T4000M_1.csv T4000M_1 t4000m_1_db T4000M_1.sql` cache_clear elapsed2=`psql_import T4000M_1.csv T4000M_1 t4000m_1_db T4000M_1.sql` cache_clear elapsed3=`psql_import T4000M_1.csv T4000M_1 t4000m_1_db T4000M_1.sql` echo 4000M: `avg $elapsed1 $elapsed2 $elapsed3` # 8000M cache_clear elapsed1=`psql_import T8000M_1.csv T8000M_1 t8000m_1_db T8000M_1.sql` cache_clear elapsed2=`psql_import T8000M_1.csv T8000M_1 t8000m_1_db T8000M_1.sql` cache_clear elapsed3=`psql_import T8000M_1.csv T8000M_1 t8000m_1_db T8000M_1.sql` echo 8000M: `avg $elapsed1 $elapsed2 $elapsed3` # 12000M cache_clear elapsed1=`psql_import T12000M_1.csv T12000M_1 t12000m_1_db T12000M_1.sql` cache_clear elapsed2=`psql_import T12000M_1.csv T12000M_1 t12000m_1_db T12000M_1.sql` cache_clear elapsed3=`psql_import T12000M_1.csv T12000M_1 t12000m_1_db T12000M_1.sql` echo 12000M: `avg $elapsed1 $elapsed2 $elapsed3`
wal_mode = minimal で実行したとき
wal_mode = replica で実行したとき