teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

5

バルクインサートについて追記

2020/07/14 20:55

投稿

yymmt
yymmt

スコア1615

answer CHANGED
@@ -38,4 +38,10 @@
38
38
  rows = []
39
39
  if len(rows) > 0:
40
40
  cur.executemany(sql, rows)
41
- ```
41
+ ```
42
+
43
+ [追記]
44
+ どうやらpsycopg2からバルクインサートが使えるようなので参考URLを紹介。cur.executemany(sql, rows)をextras.execute_values(cur, sql, rows)にするだけで良いらしい。
45
+
46
+ - [1000万件のINSERTを映画1本分ぐらい時間節約できた話](https://datumstudio.jp/blog/postgresql%E3%81%A7insert%E9%80%9F%E5%BA%A6%E6%AF%94%E8%BC%83)
47
+ - [Postgresqlでバルクインサートする方法](https://qiita.com/K-1/items/f37654f5355f593c815f)

4

引数のミスを修正

2020/07/14 20:55

投稿

yymmt
yymmt

スコア1615

answer CHANGED
@@ -37,5 +37,5 @@
37
37
  cur.executemany(sql, rows)
38
38
  rows = []
39
39
  if len(rows) > 0:
40
- cur.executemany(rows)
40
+ cur.executemany(sql, rows)
41
41
  ```

3

Prepared Statementを追記

2020/07/14 20:40

投稿

yymmt
yymmt

スコア1615

answer CHANGED
@@ -18,4 +18,24 @@
18
18
  if i % commit_limit == (commit_limit - 1):
19
19
  cur.commit()
20
20
  cur.commit()
21
+ ```
22
+ あるいはPrepared statementを使って
23
+ ```python
24
+ import csv
25
+ import psycopg2
26
+
27
+ sql = "INSERT INTO [テーブル] VALUES (%s, %s, %s)" # %sはカラムの数だけ書く
28
+ commit_limit = 1000 # 1000回に1回コミットする
29
+ with psycopg2.connect("****") as conn, open('[CSVファイル]', 'r') as f:
30
+ with conn.cursor() as cur:
31
+ reader = csv.reader(f)
32
+ next(reader) # ヘッダ行をスキップ
33
+ rows = []
34
+ for i, row in enumerate(reader):
35
+ rows.append(row)
36
+ if i % commit_limit == (commit_limit - 1):
37
+ cur.executemany(sql, rows)
38
+ rows = []
39
+ if len(rows) > 0:
40
+ cur.executemany(rows)
21
41
  ```

2

内容を正確にした

2020/07/14 20:39

投稿

yymmt
yymmt

スコア1615

answer CHANGED
@@ -1,4 +1,4 @@
1
- `\copy`はCOPYコマンドと異なり`psql`のコマンドですので、execute()で流し込むSQLとして使用することは出来ません。メモリ確保をしたくないということですので恐らく比較的ファイルサイズの大きなCSVファイルだと想像します。そのような場合、経験上INSERT文よりもCOPYコマンドのほうが(圧倒的に)高速ですので、特段の理由がない限りpsqlを使うことをお勧めします。
1
+ `\copy`はCOPYコマンドと異なり`psql`のコマンドですので、execute()で流し込むSQLとして使用することは出来ません。メモリ確保をしたくないということですので恐らく比較的ファイルサイズの大きなCSVファイルだと想像します。そのような場合、経験上INSERT文よりもCOPYコマンドのほうが(圧倒的に)高速ですので、特段の理由がない限りpsqlからCOPYコマンドを使うことをお勧めします。
2
2
 
3
3
  遅くても構わないのでPythonで行いたいということであれば(copy_fromを使わない方法としては)、INSERT文を組み立てることになります。一行ずつだと遅いのでcommitはある程度まとまってからcommitするほうが良いです。
4
4
 

1

typoの修正

2020/07/14 20:21

投稿

yymmt
yymmt

スコア1615

answer CHANGED
@@ -1,4 +1,4 @@
1
- `\copy`はCOPYコマンドと異なり`psql`のコマンドですので、execute()で流し込むSQLとして使用することは出来ません。メモリ確保をしたくないということですので恐らく比較的ファイルサイズの大きなCSVファイルだと想像します。そのような場合、経験上INSERT文よりもCOPYコマンドのほうが(圧倒的に)高速ですので、特段の理由がない限りpsqlを使うことをお勧めします。
1
+ `\copy`はCOPYコマンドと異なり`psql`のコマンドですので、execute()で流し込むSQLとして使用することは出来ません。メモリ確保をしたくないということですので恐らく比較的ファイルサイズの大きなCSVファイルだと想像します。そのような場合、経験上INSERT文よりもCOPYコマンドのほうが(圧倒的に)高速ですので、特段の理由がない限りpsqlを使うことをお勧めします。
2
2
 
3
3
  遅くても構わないのでPythonで行いたいということであれば(copy_fromを使わない方法としては)、INSERT文を組み立てることになります。一行ずつだと遅いのでcommitはある程度まとまってからcommitするほうが良いです。
4
4