从PostgreSQL到Elasticsearch索引海量数据(约1200万行)非常慢

时间:2018-11-27 11:54:06

标签: php laravel postgresql elasticsearch optimization

我正在使用postgreSQL,并且正在尝试将Elasticsearch的功能引入我们的系统。我正在使用此算法将数据(每次 1000行)批量插入Elasticsearch。问题是它非常非常缓慢,仅需 28万行数据就花费了 15小时

根据我的估计,仅需要 26天就可以完成仅对该表的索引编制(具有约1200万条记录)。

是否有可能以某种方式优化此方法并创建更快的方法?这是我到目前为止所做的:

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 = [];
        }
    }

P.S:我正在使用elasticaElasticsearch一起工作,并且该应用程序位于Laravel 5.7中,并且postgreSQL作为主数据库。

P.S:ElasticSearch website中也建议使用这种方法,但是对于我正在处理的数据量来说,它仍然太慢了。

2 个答案:

答案 0 :(得分:1)

问题是由于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();

答案 1 :(得分:0)

尝试将mapping添加到您的索引。还要检查是否需要分析每个字段-https://www.elastic.co/guide/en/elasticsearch/reference/2.3/mapping-index.html