Php 从大文本文件获取数据的最快方法

Php 从大文本文件获取数据的最快方法,php,performance,bigdata,Php,Performance,Bigdata,我正在下载一些文件,每个文件都是100mb大小,压缩为.gz。当我解压缩它们时,它们的大小是350MB 在此文件中,在语言的开头有一些标识,如英语的en,德语的de 旁边有一些我需要保存的数字。此文件中的一行示例如下所示 de Gemeinschaft\u nicht-anerkanner\u staten 1 10446 正如我所说的,这个文件非常大,我有多个文件(多个文件中总共有大约1tb的数据,每个文件有300mb的数据) 现在,我正在做以下工作: 由于还有其他语言,我首先只得到以de开头

我正在下载一些文件,每个文件都是100mb大小,压缩为.gz。当我解压缩它们时,它们的大小是350MB

在此文件中,在语言的开头有一些标识,如英语的
en
,德语的
de

旁边有一些我需要保存的数字。此文件中的一行示例如下所示

de Gemeinschaft\u nicht-anerkanner\u staten 1 10446

正如我所说的,这个文件非常大,我有多个文件(多个文件中总共有大约1tb的数据,每个文件有300mb的数据)

现在,我正在做以下工作:

  • 由于还有其他语言,我首先只得到以
    de
    开头的语言
  • preg#u match_all('#^(de\s+.*)#m',file_get_contents('tmpfile.txt'),$matches)

    然后我得到了
    名称
    ,它是一行中的第二列,应该是

    在我们的示例中,
    Gemeinschaft\u nicht-anerkanner\u staten

    现在,我正在查看是否存在该特定名称和当前日期的数据库条目。如果没有,我将它保存到数据库中,否则,我通过增加一个特定的数字来“udpate”它。然而,我从今天上午11点就开始写这篇文章了,目前只有21572篇文章,而且还远没有结束。获取所有数据可能需要几周的时间。有没有比像我这样做更快的方法?这是我正在使用的代码

    请注意,正如我所说的,从5月1日开始,我每小时下载一个文件,这意味着我有24个文件,每个文件100mb(解压300mb),大约120天(4个月),这使得我必须浏览2880个文件

    <?php
    // some requires
    
    // some settings
    ignore_user_abort(true);
    set_time_limit(0);
    ini_set('memory_limit',-1);
    
    // some information about the url and file type
    $baseUrl        = 'http://dumps.wikimedia.org/other/pagecounts-raw/';
    $baseName       = 'pagecounts-';
    $fileName       = '.gz';
    
    // i want to get a file for every hour since the 1st May
    $begin      = new DateTime('2014-05-01 00:00:00');
    $end        = new DateTime(date('Y-m-d H:i:s'));
    $interval = new DateInterval('PT1H');
    $dateRange = new DatePeriod($begin, $interval, $end);
    
    iterating through every hour
    foreach ($dateRange as $date){
        /**
         * @var DateTime $date
         */
    
         // building the download url
        $url            = $baseUrl . $date->format('Y') . '/' . $date->format('Y-m') . '/' . $baseName . $date->format('Ymd-H0000') . $fileName;
        print 'Now doing file: ' . $url . '<br>';
        // downloading the file
        file_put_contents("tmpfile.gz", fopen($url , 'r'));
        // unzipping
        unzipfile('tmpfile.gz');
        // getting only german articles
        preg_match_all('#^(de\s+.*)#m', file_get_contents('tmpfile.txt'), $matches);
        $matches = $matches[0];
        foreach ($matches as $match){
            // getting the informations
            $info = explode(' ', $match);
    
            //check if already exists in database
            $pageStatistic  = new Pagestatistic();
            $state          = $pageStatistic->loadFrom([
                'articleName'       => urldecode($info[1]),
                'articleLanguage'   => 'de',
                'pageViewsDate'     => $date->format('Y-m-d')
            ]);
    
            if ($state){
                $pageStatistic->articlePageViews = $pageStatistic->articlePageViews + $info[2];
            } else {
                $pageStatistic->articleName         = urldecode($info[1]);
                $pageStatistic->articleLanguage     = 'de';
                $pageStatistic->articlePageViews    = $info[2];
                $pageStatistic->pageViewsDate       = $date->format('Y-m-d');
            }
            // save/update
            $pageStatistic->save();
        }
    }
    
    //method to unzip files
    function unzipfile($fileName){
        $buffer_size = 4096;
        $out_file_name = str_replace('.gz', '.txt', $fileName);
        $file = gzopen($fileName, 'rb');
        $out_file = fopen($out_file_name, 'wb');
        while(!gzeof($file)) {
            fwrite($out_file, gzread($file, $buffer_size));
        }
        fclose($out_file);
        gzclose($file);
    }
    

    从文本文件中提取数据似乎没问题。这里的瓶颈是您的数据库活动。一般的建议是尝试成批处理,这会显著提高吞吐量。350MB文件上的正则表达式?祝你好运为什么不逐行阅读,一次只读一行你的逻辑呢?代替正则表达式,您可以在空格上分解并检查第一部分是否为
    de
    ,等等。不要使用
    file\u get\u contents
    ,因为它会将您的所有数据加载到内存中,也就是说,只有350mb的ram才能加载文件。接下来,您要对文件内容进行预匹配,这也是您正在做的一件高内存使用率的事情。相反,使用fopen获取文件句柄,逐行读取文件,并仅对该行应用正则表达式。您可以使用
    strpos()
    查找语言,也就是说,因为strpos更快,所以不使用正则表达式。kingkero-正则表达式“非常快”。获取所有结果所需时间不到1秒。是db插入花费了很多时间@SergioTulentsev你说的是多查询,而不是对每个匹配都执行一个查询吗?嗨,谢谢你的回答,我会“修复”正则表达式和下载的问题,但问题仍然存在,因为插入需要时间,正则表达式只需不到1秒的时间。多重查询能解决这个问题吗?