MySQL将Redis放在一张巨大的桌子上,如何加快速度?

时间:2012-04-16 09:39:16

标签: php mysql redis

当我尝试将大量数据从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万行数据,约为。 800 MB的大小。 但是我需要在以后对更大的表做类似的事情。

1 个答案:

答案 0 :(得分:2)

首先,您可能想要使用其他脚本语言。 Perl,Python,Ruby,运行这种脚本比PHP更好。

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

这意味着:

  • 您不应该使用无缓冲的查询,而应使用缓冲的查询(在查询中使用LIMIT)

OR

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

  • 您应该管理您发送给Redis的命令

以下是使用Predis进行流水线操作的示例: https://github.com/nrk/predis/blob/v0.7/examples/PipelineContext.php

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