我是整个php / mysql的新手。我有一周的服务器日志(大约300,000项),我需要做一些分析。我打算将它们全部读入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;
}
答案 0 :(得分:5)
如果你的桌子很大,你不想做SELECT * FROM MYTABLE
,你将会把整件事放在记忆中。内存开销和数据库调用之间的权衡将是批处理请求。您可以在表格中获取行的最小和最大ID:
SELECT MIN(ID) FROM MYTABLE;
SELECT MAX(ID) FROM MYTABLE;
现在从minId循环到maxId,每次增加10,000。在伪代码中:
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;
}
答案 1 :(得分:4)
见这里:
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 :(得分:2)
使用mysql_fetch_*
$result = mysql_query(...);
while($row = mysql_fetch_assoc($result)) {
$curIndex = $row['index'];
}
我认为以“流式”方式检索结果,而不是一次性将它们全部加载到内存中。我不确定mysql_result
到底是做什么的。
答案 3 :(得分:0)
在理想的世界中,PHP会生成聚合查询,将它们发送到MySQL,并且只返回少量行。例如,如果您计算两个日期之间每个严重性的日志项数:
SELECT COUNT(*), severity
FROM logs
WHERE date < ? AND date > ?
GROUP BY severity
在PHP方面做的工作很不寻常。如果你发现你需要处理太复杂的SQL查询来处理(考虑到你可以控制你的数据库结构,让你有很大的自由),一个更好的选择就是转移到Map-Reduce数据库引擎就像CouchDB。
答案 4 :(得分:0)
我坚信使用Doctrine进行批处理或使用MySQL(PDO或mysqli)进行任何迭代都只是一种错觉。
@ dimitri-k提供了一个很好的解释,特别是关于工作单元。问题是导致错过:&#34; $ query-&gt; iterate()&#34;它并没有真正迭代数据源。已经完全获取数据源的只是一个\ Traversable wrapper 。
一个例子表明即使从图片中完全删除Doctrine抽象层,我们仍会遇到内存问题:
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 Doctrine或DQL或纯SQL来传输繁重的表。但是你找到了合适的:https://github.com/EnchanterIO/remote-collection-stream