php千万级数据怎么优化,mysql千万级数据如何做优化

本帖最后由 demofere 于 2015-02-11 13:56:31 编辑 function insert(){

global $m;

if (!isset($_REQUEST['strs']) || !isset($_REQUEST['type'])

|| !isset($_REQUEST['hash'])){

echo 'param error';

return;

}

//strs为所有字符串

$poststr = $_REQUEST['strs'];

$xstrs = json_decode(stripslashes($poststr), true);

$type = $_REQUEST['type'];

$hash = $_REQUEST['hash'];

if (count($xstrs) <= 0){

$msg = 'str error';

DsLog::errLog($msg.$poststr);

echo $msg;

return;

}

if ($type == '0'){

$table = 'white';

}

else if($type == '1'){

$table = 'black';

}

else{

$msg = 'type error';

DsLog::errLog($msg);

echo $msg;

return;

}

$strs = array();

for($i = 0; $i < count($xstrs); $i++) {

$strtmp = $xstrs[$i];

$strtmp = trim($strtmp);

$strtmp = strtolower($strtmp);

$strtmp = addslashes($strtmp);

if (strlen($strtmp) > 256){

$strtmp = substr($strtmp, 0, 256);

}

if (strlen($strtmp) >= 7)

{

array_push($strs, $strtmp);

}

}

//拼接所有字符串

$tmp = '("'.implode('","', $strs).'")';

//获取已存在的字符串

$sql = "select * from $table where str in $tmp";

$ret = mysql_query($sql, $m);

if (!$ret){

$msg = 'exec error:'.mysql_error($m).','.$sql;

DsLog::errLog($msg);

echo $msg;

return;

}

$exists = array();

$notexists = array();

$count = mysql_num_rows($ret);

for ($i = 0; $i < $count; $i++)

{

$item = mysql_fetch_assoc($ret);

if (!$item){

break;

}

array_push($exists, $item['str']);

}

for ($i = 0; $i < count($strs); $i++){

if (in_array($strs[$i], $exists)){

continue;

}

array_push($notexists, $strs[$i]);

}

for($i = 0; $i < count($exists); $i++) {

$exists[$i] = addslashes($exists[$i]);

}

for($i = 0; $i < count($notexists); $i++) {

$notexists[$i] = addslashes($notexists[$i]);

}

if (count($exists) > 0){

//更新已存在字符串的count字段

$tmp = '("'.implode('","', $exists).'")';

$time = date('YmdHi');

$sql = "update $table set count=count+1 where str in $tmp";

$ret = mysql_query($sql, $m);

if (!$ret){

$msg = 'exec error:'.mysql_error($m).','.$sql;

DsLog::errLog($msg);

echo $msg;

return;

}

//更新已存在字符串的upd字段

$sql = "update $table set upd='$time' where str in $tmp";

$ret = mysql_query($sql, $m);

if (!$ret){

$msg = 'exec error:'.mysql_error($m).','.$sql;

DsLog::errLog($msg);

echo $msg;

return;

}

}

//插入新信息

if (count($notexists) > 0){

$time = date('YmdHi');

$sql = "insert ignore into $table (str,hash,count, upd) values";

for ($i = 0; $i < count($notexists); $i++){

$str = $notexists[$i];

$crc = sprintf("%u", crc32($str));

$sql .= "('$str','$crc','1', '$time'),";

}

$sql = substr($sql, 0, strlen($sql) - 1);

$ret = mysql_query($sql, $m);

if (!$ret){

$msg = 'insert error:'.mysql_error($m).','.$sql;

DsLog::errLog($msg);

echo $msg;

return;

}

}

echo !!$ret;

}

我现在要对字符串做统计,统计每个字符串的数量,就是类似一个map, 这符串:数量,当然,数据库顺便还保存了一下字符中的crc等信息

insert函数接收post过来的strs,这是一个字符串数组,每次post过来的字符串数量平均为1500

现在数据库里的记录1200W条,每一次insert花费的时间平均为20秒(经常出现30秒超时)

请问下各位,该怎么做优化,现在只是统计了很小一部分,预计统计完数据量大概在1-10亿条

------解决思路----------------------

你能确定瓶颈是在数据库做 查询 和 修改 的3条语句上吗?

你说 每次post过来的字符串数量平均为1500

那是指 1500 的单词吗?就算不是(是串长度)那么以平均每个单词20个字符计算,也有75个单词

你的过滤条件是 str in $tmp (str in ('xxx','xxx'....))也就是对表中的每一条记录都要做 1500(75)次字符串比较,而命中率至多是1/1500(1/75)你认为这样做合适吗?

数据库的强项在于记录间的比较,而你却在做弱势的列间比较

你可以用传入的数据构造出一个临时表(每行一个单词),再去与主表关联操作。这样才能发挥数据库的优势

再有,你的连续 2 条 update 语句不能合并在一起吗?

------解决思路----------------------

1、mysql 有内存表,你并未使用

2、将两条 update 合并,应该能减少 10 秒

------解决思路----------------------

mysql_error这种库函数的效率也不高吧而且官方也不推荐,我几乎没有用过这种,我学PHP的时候,直接开始PDO的。

还有,你用了in这个关键字,好像它是不走索引的吧。

------解决思路----------------------

引用:感觉效果差不多一样

应该是你测试环境的问题吧,联表查询大多数情况下是要比in快的

你测的结果差不多可能是如下原因

1.查询表的数据没有达到一定量

2.两种查询方式查出的结果集不同

3.查询字段未加索引或加的不对

4.被其他索引过多而影响

5.其他原因

我认为比较明显的就是第2个原因

你联表查时没有指定查询字段,联表出的字段肯定要比不连表的要多

还有联表查询会有一对多的情况,那样一条记录就会变成多条的,要加group by

相关文章

相关视频

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值