1

当我尝试从 mysql 表中获取大量数据到 redis 数据库时,我遇到了一些问题。无论如何,一段时间后我收到错误“MySQL 服务器已消失”,我不知道为什么..

编辑:

或者,当我使用中断循环的注释代码时,它只是在未完成时“完成”。

这是我使用的 php 代码(由 php-cli 运行):

<?php
require 'Predis/Autoloader.php';
Predis\Autoloader::register();

mysql_connect('localhost', 'root', 'notcorrect') or die(mysql_error());
mysql_select_db('database_that_i_use') or die(mysql_error());
$redis = new Predis\Client();

//starting on 0 but had to edit this when it crashed :(
for($i = 3410000; $i<999999999999; $i += 50000) {
        echo "Query from $i to  " . ($i + 50000) . ", please wait...\n";
        $query = mysql_unbuffered_query('SELECT * FROM table LIMIT ' . $i . ', 50000')or die(mysql_error());
        // This was code I used before, but for some reason it got valid when it wasn't supposed to. 
        /*if(mysql_num_rows($query) == 0) {
                echo "Script finished!\n";
                break;
        }*/
        while($r = mysql_fetch_assoc($query)) {
                $a = array('campaign_id' => $r['campaign_id'],
                           'criteria_id' => $r['criteria_id'],
                           'date_added' => $r['date_added'],
                );

                $redis->hmset($r['user_id'], $a);
                unset($a);
                usleep(10);
        }
        echo "Query completed for 50000 rows..\n";
        sleep(2);
}



unset($redis);
?>

我的问题是如何更好地做到这一点,我真的不知道它为什么会崩溃。我的服务器很旧而且速度很慢,可能无法处理这么大量的数据?在我们切换到实际生产之前,这只是一个测试服务器。

值得注意的是,脚本可能运行了半个小时,并且可能是限制语句在数量变高时使它变得非常慢?那么有没有更简单的方法来做到这一点?我今天需要传输所有数据!:)

提前致谢。

编辑:运行示例:

Query from 3410000 to  3460000, please wait...
Query completed for 50000 rows..
Query from 3460000 to  3510000, please wait...
Query completed for 50000 rows..
Query from 3510000 to  3560000, please wait...
Query completed for 50000 rows..
Query from 3560000 to  3610000, please wait...
MySQL server has gone away

编辑:

该表由约 500 万行数据组成,约为 500 万行。800 MB 大小。但是我以后需要为更大的桌子做类似的事情..

4

1 回答 1

1

首先,您可能想要使用另一种脚本语言。Perl、Python、Ruby,任何东西都比 PHP 更好地运行这种脚本。

我无法评论 mysql 连接丢失的原因,但为了获得更好的性能,您需要尝试尽可能多地消除 mysql 服务器和 redis 服务器的往返。

它的意思是:

  • 您不应该使用无缓冲的查询,而是使用缓冲的查询(前提是查询中使用了 LIMIT)

或者

  • 您不应该使用 LIMIT 对 mysql 查询进行迭代,因为您会得到二次复杂度,而它应该只是线性的。我不知道它是否可以在 PHP 中避免。

  • 您应该管道发送到 Redis 的命令

这是使用 Predis 进行管道化的示例: https ://github.com/nrk/predis/blob/v0.7/examples/PipelineContext.php

实际上,如果我真的必须为此使用 PHP,我会将 mysql 数据导出到一个文本文件中(例如使用“select into outfile”),然后读取该文件并使用流水线将数据推送到 Redis。

于 2012-04-16T17:01:59.657 回答