现有两张表
1.用户表(user),字段(uid,....,jifen[积分字段])
2.排行表(paihang) ,字段(id,uid,paiming[当前排名],yspaiming[上一次统计排名])目的:安装用户表(user)中积分值 从高到低排序,积分最高排名第一,这样一次往下类推 2,3,4.....现在方案:
$paiming =1;
$res = $this-> db -> query("SELECT user.id,user.jifen,ph.paiming FROM user LEFT JOIN paihang ph ON ph.uid = user.id ORDER BY user.meili DESC");
while ($value = $this->db -> fetch($res))
{
//如果排行表中没有记录,则追加记录,否则修改记录即可
if($value['paiming'] && $value['paiming']>0)
{
$this->db -> query("UPDATE paihang SET
jifen={$value['meili']},
paiming={$paiming},
yspaiming={$value['paiming']} WHERE uid = $value[id]");
}
else
{
$this-> db -> query("INSERT INTO paihang (uid,jifen,paiming,yspaiming
)VALUES(
{$value['id']},{$value['meili']},
{$paiming},$paiming)");
}
$paiming ++;
}
return true;如果当用户表比较大时,(10几万的 数据)处理就相当吃力了,求一个优化方案!!!
1.用户表(user),字段(uid,....,jifen[积分字段])
2.排行表(paihang) ,字段(id,uid,paiming[当前排名],yspaiming[上一次统计排名])目的:安装用户表(user)中积分值 从高到低排序,积分最高排名第一,这样一次往下类推 2,3,4.....现在方案:
$paiming =1;
$res = $this-> db -> query("SELECT user.id,user.jifen,ph.paiming FROM user LEFT JOIN paihang ph ON ph.uid = user.id ORDER BY user.meili DESC");
while ($value = $this->db -> fetch($res))
{
//如果排行表中没有记录,则追加记录,否则修改记录即可
if($value['paiming'] && $value['paiming']>0)
{
$this->db -> query("UPDATE paihang SET
jifen={$value['meili']},
paiming={$paiming},
yspaiming={$value['paiming']} WHERE uid = $value[id]");
}
else
{
$this-> db -> query("INSERT INTO paihang (uid,jifen,paiming,yspaiming
)VALUES(
{$value['id']},{$value['meili']},
{$paiming},$paiming)");
}
$paiming ++;
}
return true;如果当用户表比较大时,(10几万的 数据)处理就相当吃力了,求一个优化方案!!!
然后执行更新语句。语句示例为:
UPDATE paihang SET
jifen={$value['jifen']},
paiming={$paiming},
yspaiming=paiming WHERE uid = $value[id]也就是上次排名等于原来的paiming 字段
同时根据mysql_affected_rows()函数判断是否有记录被更新,没有的话再执行insert操作。
2. 这个几句sql就行,不用php一个一个insert/update
几句SQL就行?如何做的?学习
可以用笨办法, 做一个php, shell.程序段
取max最大值.排名第一
然后小于这个值的max第二.
依次往那个表里写. 看程序多久运行完. 用crontab定个时间, 排名多久更新一次就ok了.
这位大哥提醒的对,索引是建了的
2. 这个几句sql就行,不用php一个一个insert/update ??
还请赐教
alter table user add index ('id');
alter table paihang add index ('uid');
user表的meili字段是干嘛的,如果是日期的话加索引
alter table user add index ('meili');解决方案2:按照楼主的逻辑 每个用户的当前排名和上次排名应该都是唯一的值也就是说 user和paihang是一一对应关系,完全可以放一张表里面,避免使用jion 查询join查询数据量大的时候,能不就就不要用。数据库设计的时候可以用适当的冗余换取数据
继续收集良方,继续测试
insert into paihang(uid,jifen)
select u.uid, u.meili
from users u left join paihang p
on u.uid=p.uid
where p.uid is null
;
或(应该是第一个快点)
insert into paihang(uid,jifen)
select uid, meili
from users
where uid not in (select uid from paihang )
;2.更改积分
update paihang p, users u
set p.jifen=u.meili
where p.uid=u.uid
;
3.更新排名
set @c=0
;
update paihang
set yspaiming=paiming, paiming=@c:=@c+1
order by jifen desc
;你试一下, 如果有速度问题, 贴库结构和索引上来,以及explain的结果
字段越多,表越大,做任何操作的时间都会越长!
但是根据你的描述,单表查询不做更新要花费38s,比left join花费的还要多,这个不可能,你把你的代码贴出来看看就知道问题在哪里了。
也是有可能的, 要看left join里引用的字段,
楼主的user表估计是有很多的字段..... 这个还是要看表结构
另外,楼主,
看你的code里是把meili更新到排行的jifen里的,
但是user里怎么也有一个jifen???
SELECT player.id,player.meili,ph.paiming FROM player LEFT JOIN meilipaihang ph ON ph.uid = player.id ORDER BY player.meili DESC
//保存在两张表中,(注:当meilipaihang表中未空是,即没有任何记录时,200,243 总计, 查询花费 0.3445 秒,当meilipaihang不为空,有20w数据时,在7秒左右0)SELECT player.id,player.meili,paihang FROM player ORDER BY player.meili DESC
//和并表 200,243 总计, 查询花费 0.2984 秒
其中 player.id 为主键,meilipaihang.uid 唯一索引
如果放在MYSQL命令下或者PHPMYADMIN等mysql工具下运行效率相当可观,但怎么才能放的程序中执行??
由于set @c=0;有分号,表示这句执行完毕,下面的 paiming=@c:=@c+1 就找不到值了,即mysql报错
类似
update test2, (select @a:=1) x
set num=@a:=@a+1
;
偷个懒,你自己照这个例子改一下