我有一张大约有100万行的表。我正在做一个简单的程序,从每行打印出一个字段。但是,当我开始使用mysql_pconnect和mysql_query时,查询需要很长时间,我假设查询需要完成才能打印出第一行。有没有办法一次处理一点数据?
- 编辑 - 我不打算检索一小部分数据,我正在寻找一种方法来一次处理一个数据块(比如获取10行,打印10行,获取10行,打印10行等)等待查询检索100万行(谁知道多长时间),然后开始打印。
答案 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 BY
和LIMIT
来阻止订单在请求之间随意更改。
答案 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_QUERY
为false
。
编辑:正如其他人所说,您可能希望在每批处理后将其与刷新输出缓冲区结合起来,具体取决于您的具体情况。