PHP如何一次运行sql查询一部分?

时间:2009-12-14 21:10:14

标签: php sql mysql performance

我有一张大约有100万行的表。我正在做一个简单的程序,从每行打印出一个字段。但是,当我开始使用mysql_pconnect和mysql_query时,查询需要很长时间,我假设查询需要完成才能打印出第一行。有没有办法一次处理一点数据?

- 编辑 - 我不打算检索一小部分数据,我正在寻找一种方法来一次处理一个数据块(比如获取10行,打印10行,获取10行,打印10行等)等待查询检索100万行(谁知道多长时间),然后开始打印。

8 个答案:

答案 0 :(得分:3)

打印一百万个字段需要一些时间。检索一百万条记录需要一些时间。时间加起来。

您是否描述过您的代码?我不确定使用限制会在这种情况下产生如此巨大的差异。

做这样的事

while ($row = mysql_fetch_object($res)) {
   echo $row->field."\n";
}

一次输出一条记录。它不会等待返回整个结果集。

如果您正在处理浏览器,则需要更多内容。

比如这个

ob_start();
$i = 0;
while ($row = mysql_fetch_object($res)) {
   echo $row->field."\n";
   if (($i++ % 1000) == 0) {
       ob_flush();
   }
}
ob_end_flush();

答案 1 :(得分:2)

你真的想打印一百万个字段吗?

通常的解决方案是在Web应用程序中使用某种输出分页,仅显示部分结果。在SELECT次查询中,您可以使用LIMIT关键字仅返回部分数据。这是基本的SQL东西,真的。例如:

SELECT * FROM table WHERE (some conditions) LIMIT 40,20

显示20个条目,从第40个开始(我可能会犯一个错误)。

可能需要使用ORDER BYLIMIT来阻止订单在请求之间随意更改。

答案 2 :(得分:1)

分页通常需要这样做。您可以在选择查询中使用limit关键字。搜索限制here

  

LIMIT子句可用于约束SELECT语句返回的行数。 LIMIT需要一个或两个数字参数,它们都必须是非负整数常量(使用预准备语句时除外)。

     

使用两个参数,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。初始行的偏移量为0(不是1):

SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15
  

要从特定偏移量检索所有行直到结果集的末尾,可以使用一些大数字作为第二个参数。此语句检索从第96行到最后一行的所有行:

SELECT * FROM tbl LIMIT 95,18446744073709551615;
  

使用一个参数,该值指定从结果集开头返回的行数:

SELECT * FROM tbl LIMIT 5;     # Retrieve first 5 rows
  

换句话说,LIMIT row_count相当于LIMIT 0,row_count。

答案 3 :(得分:0)

您可以使用 Mysqli::use_result

结合flush将数据集输出到浏览器。我知道flush可以用于以增量状态将数据输出到浏览器,因为我之前使用过它,但是我不确定mysqli :: use_result是否是检索不完整结果集的正确函数。

答案 4 :(得分:0)

这就是我在Oracle中做类似的事情。我不确定它会如何交叉:

declare
my_counter integer := 0;
begin
for cur in (
select id from table
) loop
  begin
    -- do whatever your trying to do
    update table set name = 'steve' where id = cur.id;
    my_counter := my_counter + 1;
    if my_counter > 500 then
      my_counter := 0;
      commit;
    end if;
    end;
  end loop;
  commit;
end;

答案 5 :(得分:0)

使用基本mysql驱动程序的示例。

define( 'CHUNK_SIZE', 500 );

$result = mysql_query( 'select count(*) as num from `table`' );
$row = mysql_fetch_assoc( $result );

$totalRecords = (int)$row['num'];

$offsets = ceil( $totalRecords / CHUNK_SIZE );

for ( $i = 0; $i < $offsets; $i++ )
{
  $result = mysql_query( "select * from `table` limit " . CHUNK_SIZE . " offset " . ( $i * CHUNK_SIZE ) );
  while ( $row = mysql_fetch_assoc( $result ) )
  {
    // your per-row operations here
  }
  unset( $result, $row );
}

这将迭代整个行卷,但一次只能执行500行以减少内存使用量。

答案 6 :(得分:0)

听起来你在mysql服务器中达到了各种缓冲区大小的限制......你可以做的一些方法是在SQL语句中指定你想要的字段来减少这个缓冲区的大小,或者玩一下各种管理设置。

或者,您可以使用分页之类的方法,但让它在一个页面上输出...

(伪代码)

 function q($part) {
      $off = $part*SIZE_OF_PARTITIONS;
      $size = SIZE_OF_PARTITIONS;

      return( execute_and_return_sql('SELECT `field` FROM `table` LIMIT $off, $size'));
    }

    $ii = 0;

    while ($elements = q($ii)) {
      print_fields($elements);
      $ii++;
    }

答案 7 :(得分:0)

使用mysql_unbuffered_query()或使用PDO确保PDO::MYSQL_ATTR_USE_BUFFERED_QUERYfalse

另见this similar question

编辑:正如其他人所说,您可能希望在每批处理后将其与刷新输出缓冲区结合起来,具体取决于您的具体情况。