Индексирование огромных данных (~ 12 миллионов строк) из postgreSQL в Elasticsearch ОЧЕНЬ МЕДЛЕННО - PullRequest
0 голосов
/ 27 ноября 2018

Я использую postgreSQL и пытаюсь передать мощность Elasticsearch в нашу систему.Я использую этот алгоритм для массовой вставки данных (каждый раз 1000 строк данных) в Elasticsearch.Проблема в том, что он очень-очень медленный и занял около 15 часов всего за 280 000 строк данных.

По моей оценке, это займет около 26 дней безостановочно, чтобы завершить индексацию только этой таблицы ( с ~ 12M записями ).

Можно ли как-то оптимизировать этот подход и создать более быстрый?это то, что я делаю до сих пор:

public function run()
    {
        $es_client = new \Elastica\Client();
        $es_index = $es_client->getIndex("vehicle");
        $es_type = $es_index->getType("_doc");

        $vehicle_ins = new Vehicle;

        $step = 1000;
        $min_vehicle_id = $vehicle_ins->query()->min('id');
        $max_vehicle_id = $vehicle_ins->query()->max('id');

        $insert_counter = 1;

        $docs = [];

        for ($i = $min_vehicle_id ; $i <= $max_vehicle_id ; $i += $step) {
            $x = $i;
            $y = $i + $step;

            $vehicles = $vehicle_ins->query()
                ->where('id', '>=', $x)
                ->where('id', '<', $y)
                ->get();

            foreach ($vehicles as $vehicle) {

                $docs[] = new \Elastica\Document(
                    $vehicle->id,
                    [
                        // implementing my columns (91 columns)
                    ]);

                echo ".";

                if ($insert_counter % $step == 0) {
                    $es_type->addDocuments($docs);
                    $es_type->getIndex()->refresh();
                    $docs = [];
                    echo "\n";
                    echo $step . " rows inserted!";
                    echo "\n";
                }

                $insert_counter++;

            }
        }
        if (!empty($docs)) {
            $es_type->addDocuments($docs);
            $es_type->getIndex()->refresh();
            $docs = [];
        }
    }

PS: я использую elastica для работы с Elasticsearch, и приложение находится в Laravel 5.7 с postgreSQL в качестве основной БД.

PS: этот подход был также предложен на веб-сайте ElasticSearch , но он все еще слишком медленный для объема данных, с которыми я работаю.

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Проблема заключалась в том, что некоторые методы внутри моего Vehicle model выполняли некоторые изменения в каждом атрибуте после получения их из базы данных, и эти нежелательные изменения делали процесс очень очень медленным.

Решение состоит в том, чтобы запрашивать данные с использованием Laravel DB facade до тех пор, пока эти методы смены атрибутов не будут удалены или перенесены в другое место из модели транспортного средства .

Таким образом, запросы должны выглядетькак это:

$min_vehicle_id = \Illuminate\Support\Facades\DB::table('vehicle')->min('id');
$max_vehicle_id = \Illuminate\Support\Facades\DB::table('vehicle')->max('id');

и это для получения данных:

$vehicles = \Illuminate\Support\Facades\DB::table('vehicle')
                ->where('id', '>=', $x)
                ->where('id', '<', $y)
                ->get();
0 голосов
/ 27 ноября 2018

Попробуйте добавить сопоставление в index .Также проверьте, нужен ли вам анализ каждого поля - https://www.elastic.co/guide/en/elasticsearch/reference/2.3/mapping-index.html

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