在Laravel中播种大数据的最佳案例

时间:2013-10-30 12:34:55

标签: laravel laravel-4

我有一个包含超过30,000条记录的文件,另一条有41,000条记录。有没有最好的案例研究使用laravel 4的db:seed命令播种?一种使插入更快速的方法。

感谢您的帮助。

4 个答案:

答案 0 :(得分:5)

不要害怕,40K行表是一种小型的。我有一个1百万行的表,种子顺利完成,我只需要在做之前添加它:

DB::disableQueryLog();

在禁用它之前,Laravel浪费了我所有的PHP内存限制,无论我给它多少。

我使用fgets()从.txt文件中读取数据,以编程方式构建数组并执行:

DB::table($table)->insert($row);

一个接一个,可能特别慢。

我的数据库服务器是PostgreSQL,插入大约需要1.5小时才能完成,可能是因为我使用的是使用低内存的虚拟机。我会在一台更好的机器上做一个基准测试。

答案 1 :(得分:0)

我从不同的数据库迁移,我不得不使用带有批量插入语句的原始sql(从外部文件加载)(我通过navicat导出结构,可以选择每250KiB分解插入语句)。例如:

$sqlStatements = array(
"INSERT INTO `users` (`name`, `email`)
VALUES
    ('John Doe','john.doe@gmail.com'),.....
    ('Jane Doe','jane.doe@gmail.com')",
"INSERT INTO `users` (`name`, `email`)
VALUES
    ('John Doe2','john.doe2@gmail.com'),.....
    ('Jane Doe2','jane.doe2@gmail.com')"
);

然后我循环使用insert语句并使用

执行
DB::statement($sql). 

我无法一次插入一行。我确定有更好的选择,但这至少有效,同时让我把它留在Laravel的迁移/播种中。

答案 2 :(得分:0)

我今天遇到了同样的问题。禁用查询日志还不够。看起来事件也会被解雇。

  

DB :: disableQueryLog();

     

// DO INSERTS

     

//重置事件以释放内存。

     

DB :: setEventDispatcher(new Illuminate \ Events \ Dispatcher());

答案 3 :(得分:0)

2018更新

我遇到了同样的问题,经过2天的头痛之后,我终于可以编写脚本在不到30s的时间内播种42K条目了!

您问如何?

第一种方法

此方法假定您有一个包含某些条目的数据库(在我的情况下为42k条目),并且您希望将其导入其他数据库。将数据库导出为带有标头名称的CSV文件,并将其放入项目的公共文件夹中,然后您可以解析该文件,并通过播种器将所有条目一一插入到新数据库中。

因此您的播种机将如下所示:

<?php

use Illuminate\Database\Seeder;

class {TableName}TableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $row = 1;
        if (($handle = fopen(base_path("public/name_of_your_csv_import.csv"), "r")) !== false) {
            while (($data = fgetcsv($handle, 0, ",")) !== false) {
                if ($row === 1) {
                    $row++;
                    continue;
                }
                $row++;

                $dbData = [
                    'col1' => '"'.$data[0].'"',
                    'col2' => '"'.$data[1].'"',
                    'col3' => '"'.$data[2].'"',
                    so on...how many columns you have
                ];

                $colNames = array_keys($dbData);

                $createQuery = 'INSERT INTO locations ('.implode(',', $colNames).') VALUES ('.implode(',', $dbData).')';

                DB::statement($createQuery, $data);
                $this->command->info($row);
            }
            fclose($handle);
        }
    }
}

简单易用:)


第二种方法

如果您可以修改PHP的设置并为特定的脚本分配较大的大小,则此方法也将起作用。

基本上,您需要专注于三个主要步骤:

  • 为脚本分配更多的内存
  • 关闭查询记录器
  • 以1000个大块划分数据
  • 遍历数据并使用insert()一次创建1K的块。

因此,如果我将上述所有步骤组合到播种机中,则您的播种机将如下所示:

<?php

use Illuminate\Database\Seeder;

class {TableName}TableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        ini_set('memory_limit', '512M');//allocate memory
        DB::disableQueryLog();//disable log
        //create chunks
        $data = [
           [
              [
                 'col1'=>1,
                 'col2'=>1,
                 'col3'=>1,
                 'col4'=>1,
                 'col5'=>1
              ],
              [             
                 'col1'=>1,
                 'col2'=>1,
                 'col3'=>1,
                 'col4'=>1,
                 'col5'=>1
              ],
              so on..until 1000 entries 
           ],
           [
              [
                 'col1'=>1,
                 'col2'=>1,
                 'col3'=>1,
                 'col4'=>1,
                 'col5'=>1
              ],
              [             
                 'col1'=>1,
                 'col2'=>1,
                 'col3'=>1,
                 'col4'=>1,
                 'col5'=>1
              ],
              so on..until 1000 entries 
           ],
           so on...until how many entries you have, i had 42000
      ]
      //iterate and insert
      foreach ($data as $key => $d) {
          DB::table('locations')->insert($d);
          $this->command->info($key);//gives you an idea where your iterator is in command line, best feeling in the world to see it rising if you ask me :D
      }
  }
}

和VOILA,你很好:)

我希望对您有帮助