Альтернатива предотвращению дубликатов при импорте CSV в CouchDB - PullRequest
2 голосов
/ 08 мая 2011

У меня есть 2 больших файла CSV с миллионами строк.Поскольку эти 2 CSV-файла взяты из MySQL, я хочу объединить эти 2 таблицы в один Document в диване DB.

Какой самый эффективный способ сделать это?

Мой текущий метод:

  1. импорт 1-го CSV
  2. импорт 2-го CSV

Чтобы избежать дублирования, программа будет искать документ с ключом для каждой строки.после того, как строка найдена, Документ обновляется столбцами из второго CSV

Проблема в том, что поиск каждой строки действительно занимает много времени.при импорте второго CSV он обновляет 30 документов в секунду, и у меня около 7 миллионов строк.по приблизительным подсчетам, весь импорт займет около 64 часов.

Спасибо

Ответы [ 2 ]

2 голосов
/ 09 мая 2011

Другой вариант - просто делать то, что вы уже делаете, но использовать API для массовых документов, чтобы повысить производительность.

Для каждой партии документов:

  1. POST до /db/_all_docs?include_docs=true с таким телом:

    { "keys": [ "some_id_1"
              , "some_id_2"
              , "some_id_3"
              ]
    }
    
  2. Создайте обновление _bulk_docs в зависимости от полученных результатов.

    • Документ уже существует, вы должны обновить его: {"key":"some_id_1", "doc": {"existing":"data"}}
    • Док не существует, вы должны создать его: {"key":"some_id_2", "error":"not_found"}
  3. POST до /db/_bulk_docs с таким телом:

    { "docs": [ { "_id": "some_id_1"
                , "_rev": "the _rev from the previous query"
                , "existing": "data"
                , "perhaps": "some more data I merged in"
                }
              , { "_id": "some_id_2"
                , "brand": "new data, since this is the first doc creation"
                }
              ]
    }
    
2 голосов
/ 09 мая 2011

Похоже, у вас есть «первичный ключ», который вы знаете по строке (или вы можете вычислить его по строке). Это идеально подходит в качестве документа _id.

Проблема в том, что вы получите 409 Conflict, если попытаетесь добавить 2-ые данные CSV, но уже был документ с тем же _id. Это верно? (Если так, пожалуйста, поправьте меня, чтобы я мог исправить ответ.)

Я думаю, что есть хороший ответ для вас:

Используйте _bulk_docs для импорта всего, а затем исправьте конфликты.

Начните с чистой базы данных.

Используйте API-интерфейс Bulk document , чтобы вставить все строки из 1-го и 2-го наборов CSV - как можно больше на HTTP-запрос, например, 1000 за один раз. (Массовые документы гораздо быстрее, чем вставка по одному.)

Всегда добавить "all_or_nothing": true в ваши _bulk_docs данные POST. Это будет гарантировать, что каждая вставка будет успешной (при условии отсутствия сбоев, таких как потеря питания или Full HD).

Когда вы закончите, некоторые документы будут конфликтовать , что означает, что вы вставили дважды для одного и того же значения _id. Это не проблема. Просто выполните эту процедуру, чтобы объединить две версии:

  1. Для каждого _id, в котором есть конфликты, извлеките его с дивана на GET /db/the_doc_id?conflicts=true.
  2. Объединить все значения из конфликтующих версий в новую окончательную версию документа.
  3. Зафиксируйте окончательный объединенный документ в CouchDB и удалите конфликтующие ревизии. См. Раздел «Подробное руководство по CouchDB» в разделе разрешение конфликтов . (Вы можете использовать _bulk_docs, чтобы ускорить это тоже.)
* * Пример тысяча сорок-один * * тысяча сорок-дв

Надеюсь, это немного прояснит. Обратите внимание, я установил * manage_couchdb * couchapp из http://github.com/iriscouch/manage_couchdb. Он имеет простой вид для отображения конфликтов.

$ curl -XPUT -Hcontent-type:application/json localhost:5984/db
{"ok":true}

$ curl -XPOST -Hcontent-type:application/json localhost:5984/db/_bulk_docs --data-binary @-
{ "all_or_nothing": true
, "docs": [ { "_id": "some_id"
            , "first_value": "This is the first value"
            }
          , { "_id": "some_id"
            , "second_value": "The second value is here"
            }
          ]
}
[{"id":"some_id","rev":"1-d1b74e67eee657f42e27614613936993"},{"id":"some_id","rev":"1-d1b74e67eee657f42e27614613936993"}]

$ curl localhost:5984/db/_design/couchdb/_view/conflicts?reduce=false\&include_docs=true
{"total_rows":2,"offset":0,"rows":[
{"id":"some_id","key":["some_id","1-0cb8fd1fd7801b94bcd2f365ce4812ba"],"value":{"_id":"some_id","_rev":"1-0cb8fd1fd7801b94bcd2f365ce4812ba"},"doc":{"_id":"some_id","_rev":"1-0cb8fd1fd7801b94bcd2f365ce4812ba","first_value":"This is the first value"}},
{"id":"some_id","key":["some_id","1-d1b74e67eee657f42e27614613936993"],"value":{"_id":"some_id","_rev":"1-d1b74e67eee657f42e27614613936993"},"doc":{"_id":"some_id","_rev":"1-d1b74e67eee657f42e27614613936993","second_value":"The second value is here"}}
]}

$ curl -XPOST -Hcontent-type:application/json localhost:5984/db/_bulk_docs --data-binary @-
{ "all_or_nothing": true
, "docs": [ { "_id": "some_id"
            , "_rev": "1-0cb8fd1fd7801b94bcd2f365ce4812ba"
            , "first_value": "This is the first value"
            , "second_value": "The second value is here"
            }
          , { "_id": "some_id"
            , "_rev": "1-d1b74e67eee657f42e27614613936993"
            , "_deleted": true
            }
          ]
}
[{"id":"some_id","rev":"2-df5b9dc55e40805d7f74d1675af29c1a"},{"id":"some_id","rev":"2-123aab97613f9b621e154c1d5aa1371b"}]

$ curl localhost:5984/db/_design/couchdb/_view/conflicts?reduce=false\&include_docs=true
{"total_rows":0,"offset":0,"rows":[]}

$ curl localhost:5984/db/some_id?conflicts=true\&include_docs=true
{"_id":"some_id","_rev":"2-df5b9dc55e40805d7f74d1675af29c1a","first_value":"This is the first value","second_value":"The second value is here"}

Последние две команды показывают, что конфликтов нет, и «объединенный» документ теперь используется как «some_id».

...