代码之家  ›  专栏  ›  技术社区  ›  sixtyfootersdude

PHP/MYSQL:遍历数据库中的每个记录

  •  3
  • sixtyfootersdude  · 技术社区  · 14 年前

    我对整个php/mysql还不熟悉。我有一周的服务器日志(大约300000条),我需要做一些分析。我计划将它们全部读入mysql数据库,然后用php分析它们。

    我不确定的是如何迭代它们。使用java读取文件,我将执行以下操作:

    Scanner s = new Scanner(myfile);
    while(s.hasNext()){
        String line = s.nextLine();
        ~~ Do something with this record. 
    }
    

    如何使用php遍历mysql数据库中的所有记录?我想这样的事情会占用大量的记忆。

        $query = "SELECT * FROM mytable";
        $result = mysql_query($query);
        $rows = mysql_num_rows($result);
        for($j = 0; $j < $rows; ++$j){
                $curIndex   = mysql_result($result,$j,"index");
                $curURL     = mysql_result($result,$j,"something");
                ~~ Do something with this record
        }
    

    因此,我给select语句添加了一个限制,并重复该操作,直到所有记录都循环通过为止。有没有更标准的方法来做这件事?有内置的可以做到这一点吗?

    while($startIndex < $numberOfRows){
    
        $query = "SELECT * FROM mytable ORDERBY mytable.index LIMIT $startIndex,$endIndex";
        $result = mysql_query($query);
        $rows = mysql_num_rows($result);
        for($j = 0; $j < $rows; ++$j){
                $curIndex   = mysql_result($result,$j,"index");
                $curURL     = mysql_result($result,$j,"something");
                ~~ Do something with this record
        }
        $startIndex = $endIndex + 1;
        $endIndex = $endIndes + 10;
    }
    
    5 回复  |  直到 14 年前
        1
  •  4
  •   SW4    14 年前

    请看这里:

    http://www.tizag.com/mysqlTutorial/

    http://www.tizag.com/mysqlTutorial/mysqlfetcharray.php

    <?php
    // Make a MySQL Connection
    $query = "SELECT * FROM example"; 
    
    $result = mysql_query($query) or die(mysql_error());
    
    
    while($row = mysql_fetch_array($result)){
        echo $row['name']. " - ". $row['age'];
        echo "<br />";
    }
    ?>
    

    根据需要对结果行执行的操作,可以使用不同的循环样式,无论 while ', ' for each '或' for x to x '. 大多数情况下,一个简单的“while”迭代将是非常好的,并且是有效的。

        2
  •  5
  •   Richard H    14 年前

    你不想做 SELECT * FROM MYTABLE 如果你的桌子很大,你就要记住整件事。内存开销和数据库调用之间的一个折衷方案是批处理请求。您可以获取表中行的最小和最大id:

    SELECT MIN(ID) FROM MYTABLE;
    SELECT MAX(ID) FROM MYTABLE;
    

    现在从minId循环到maxId,每次递增10000。在伪代码中:

    for (int i = minId; i < maxId; i = i + 10000) {
       int x = i;
       int y = i + 10000;
       SELECT * FROM MYTABLE WHERE ID >= x AND ID < y;
    }
    
        3
  •  2
  •   Bart van Heukelom    14 年前

    使用 mysql_fetch_*

    $result = mysql_query(...);
    while($row = mysql_fetch_assoc($result)) {
     $curIndex = $row['index'];
    }
    

    我认为检索结果的方式是“流式”的,而不是一次将它们全部加载到内存中。我不知道到底是什么 mysql_result 做。

    旁注:既然你还是新来的,我建议你马上养成好习惯,马上跳过 mysql_ 函数和go for PDO 或者至少 mysqli .

        4
  •  0
  •   Victor Nicollet    14 年前

    在理想的情况下,PHP会生成聚合查询,并将其发送到MySQL,只得到少量的行作为回报。例如,如果要计算两个日期之间每个严重性的日志项数:

    SELECT COUNT(*), severity 
    FROM logs
    WHERE date < ? AND date > ?
    GROUP BY severity
    

    在PHP端做这项工作是很不寻常的。如果您发现需要处理的SQL查询太复杂(考虑到您可以控制数据库结构,这会给您带来很大的自由),那么更好的选择是移动到像CouchDB这样的Map-Reduce数据库引擎。

        5
  •  0
  •   Lukas Lukac    7 年前

    我坚信使用Doctrine进行批处理或使用MySQL(PDO或mysqli)进行任何形式的迭代都只是一种幻觉。

    @dimitri-k给出了一个很好的解释,特别是关于工作单元的解释。问题是缺少引导:“ $query->迭代() “它并不真正在数据源上迭代。它是 只是一个可遍历的包装 已经在附近了 完全提取 数据源。

    一个例子表明,即使从图中完全删除条令抽象层,我们仍然会遇到 内存问题 :

    echo 'Starting with memory usage: ' . memory_get_usage(true) / 1024 / 1024 . " MB \n";
    
    $pdo  = new \PDO("mysql:dbname=DBNAME;host=HOST", "USER", "PW");
    $stmt = $pdo->prepare('SELECT * FROM my_big_table LIMIT 100000');
    $stmt->execute();
    
    while ($rawCampaign = $stmt->fetch()) {
        // echo $rawCampaign['id'] . "\n";
    }
    
    echo 'Ending with memory usage: ' . memory_get_usage(true) / 1024 / 1024 . " MB \n";
    

    输出:

    Starting with memory usage: 6 MB 
    Ending with memory usage: 109.46875 MB
    

    这里,令人失望的 getIterator() 方法:

    namespace Doctrine\DBAL\Driver\Mysqli\MysqliStatement
    
    /**
     * {@inheritdoc}
     */
    public function getIterator()
    {
        $data = $this->fetchAll();
    
        return new \ArrayIterator($data);
    }
    

    你可以用我的小图书馆 事实上 使用PHP原则或DQL或纯SQL来流式处理重表。但你觉得合适: https://github.com/EnchanterIO/remote-collection-stream