Использование COPY FROM stdin для загрузки таблиц, чтение входного файла только один раз

У меня большой (~ 60 миллионов строк) исходный файл фиксированной ширины с ~ 1800 записями в строке.

Мне нужно загрузить этот файл в 5 разных таблиц на экземпляре Postgres 8.3.9.

Моя дилемма в том, что, поскольку файл очень большой, мне бы хотелось прочитать его только один раз.

Это достаточно просто, используя INSERT или COPY, как обычно, но я пытаюсь повысить скорость загрузки, включив мои операторы COPY FROM в транзакцию, которая включает TRUNCATE - избегая ведения журнала, что должно дать значительный увеличение скорости загрузки (согласно http://www.cirrusql.com/node/3 ). Насколько я понимаю, вы можете отключить вход в Postgres 9.x - но у меня нет этой опции на 8.3.9.

В приведенном ниже сценарии я дважды читаю входной файл, чего я хочу избежать ... есть идеи о том, как мне этого добиться, прочитав входной файл только один раз? Не обязательно быть bash - я также пытался использовать psycopg2, но не мог понять, как направить вывод файла в оператор COPY, как я делаю ниже. Я не могу скопировать файл, потому что мне нужно проанализировать его на лету.

#!/bin/bash

table1="copytest1"
table2="copytest2"

#note: $1 refers to the first argument used when invoking this script
#which should be the location of the file one wishes to have python
#parse and stream out into psql to be copied into the data tables

( echo 'BEGIN;'
  echo 'TRUNCATE TABLE ' ${table1} ';'
  echo 'COPY ' ${table1} ' FROM STDIN'
  echo "WITH NULL AS '';"
  cat $1 | python2.5 ~/parse_${table1}.py 
  echo '\.'
  echo 'TRUNCATE TABLE ' ${table2} ';'
  echo 'COPY ' ${table2} ' FROM STDIN'
  echo "WITH NULL AS '';"
  cat $1 | python2.5 ~/parse_${table2}.py 
  echo '\.'
  echo 'COMMIT;'
) | psql -U postgres -h chewy.somehost.com -p 5473 -d db_name

exit 0

Спасибо!

4 голоса | спросил Stew 5 MarpmSat, 05 Mar 2011 17:43:14 +03002011-03-05T17:43:14+03:0005 2011, 17:43:14

2 ответа


0

Вы можете использовать именованные каналы вместо своего анонимного канала. Благодаря этой концепции ваш скрипт на python может заполнять таблицы через различные процессы psql соответствующими данными.

Создать трубы:

mkfifo fifo_table1
mkfifo fifo_table2

Запустите экземпляры psql:

psql db_name < fifo_table1 &
psql db_name < fifo_table2 &

Ваш скрипт на python будет выглядеть примерно так (псевдокод):

SQL_BEGIN = """
BEGIN;
TRUNCATE TABLE %s;
COPY %s FROM STDIN WITH NULL AS '';
"""
fifo1 = open('fifo_table1', 'w')
fifo2 = open('fifo_table2', 'w')

bigfile = open('mybigfile', 'r')

print >> fifo1, SQL_BEGIN % ('table1', 'table1') #ugly, with python2.6 you could use .format()-Syntax     
print >> fifo2, SQL_BEGIN % ('table2', 'table2')      

for line in bigfile:
  # your code, which decides where the data belongs to
  # if data belongs to table1
  print >> fifo1, data
  # else
  print >> fifo2, data

print >> fifo1, 'COMMIT;'
print >> fifo2, 'COMMIT;'

fifo1.close()
fifo2.close()

Возможно, это не самое элегантное решение, но оно должно работать.

ответил johnbaum 6 MaramSun, 06 Mar 2011 02:10:45 +03002011-03-06T02:10:45+03:0002 2011, 02:10:45
0

Зачем использовать COPY для второй таблицы? Я бы предположил, что делает:

INSERT INTO table2 (...)
ВЫБРАТЬ ...
ИЗ таблицы 1;

будет быстрее, чем использование COPY.

Edit
Если вам нужно импортировать разные строки в разные таблицы, но из одного и того же исходного файла, возможно, вставьте все в промежуточную таблицу и затем вставьте строки оттуда в целевые таблицы:

Импортируйте текстовый файл. весь * в одну промежуточную таблицу:

COPY staging_table FROM STDIN ...;

После этого шага весь входной файл находится в staging_table

Затем скопируйте строки из промежуточной таблицы в отдельные таблицы назначения, выбрав только те из них, которые подходят для соответствующей таблицы:

INSERT INTO table_1 (...)
ВЫБРАТЬ ...
FROM staging_table
ГДЕ (условия для таблицы_1);

INSERT INTO table_2 (...)
ВЫБРАТЬ ...
FROM staging_table
ГДЕ (условия для таблицы_2);

Это, конечно, возможно, только если в вашей базе данных достаточно места для хранения промежуточной таблицы.

ответил a_horse_with_no_name 5 MarpmSat, 05 Mar 2011 17:48:40 +03002011-03-05T17:48:40+03:0005 2011, 17:48:40

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132