您正在查看: 包含标签 PHP 下的文章

[性能优化] MySQL ORDER BY RAND()的替代方案

这是开发签到助手时遇到的问题……

需求:从数据库取没有签到的TID

原来的代码:

SELECT tid FROM sign_log WHERE status IN (0, 1) AND date='{$date}' ORDER BY RAND() LIMIT 0,1

当 sign_log 这个表非常大的时候,会出现 filesort 罢工的现象

EXPLAIN 的提示:Using where; Using temporary; Using filesort

这是由于 MySQL 在执行过程中需要遍历数据库,然后给每行分配一个权重值(因为用的是RAND函数),之后再用 filesort 的方式排序临时表,最后输出。

只是取一个tid而已……有必要遍历整个表么?有没有替代的方案呢?

答案是肯定的。这个算法分为3步,将上面一个查询拆解为2个:

1.从数据库取出最大数据量:

SELECT COUNT(*) FROM `sign_log` WHERE status IN (0, 1) AND date='{$date}'

2.用 PHP 的 rand 函数计算出 offset 值

$offset = rand(1, $count) - 1;

3.直接从数据库取出这一行的tid:

SELECT tid FROM `sign_log` LIMIT {$offset},1

(再次运行时可以略过第一步)

测试结果(共13506行数据):

ORDER BY RAND():
Using where; Using temporary; Using filesort
运行时间:0.0050160884857178秒

优化后:
查询1:Using where
查询2:Using index(注:tid字段有索引)
总运行时间:0.0021970272064209秒

改进后不仅提升了运行速度,还解决了 filesort 数据量上限的问题

清理两个QQ群中的重复成员

今天清理了下 MiOTA 三个群的重复成员

本想用QQ机器人的,谁知道是腾讯抽了还是机器人抽了,怎么也无法检测出来……
没办法,还得自己动手……

好吧,惯例打开qun.qq.com,发现腾讯这货又改版了……不难想象无法检测的原因

注意到群成员列表的网址:(其中235705139为群号)
http://qun.qzone.qq.com/group#!/235705139/member

本想直接正则抓的,后来一看 Chrome 的 Network 面板,有现成的:
http://qun.qzone.qq.com/cgi-bin/get_group_member?uin=71881****&groupid=235705139&random=*******&g_tk=125454***

我这省略了几个参数,uin是QQ号,random顾名思义是随机数,g_tk这货貌似是类似token般的存在,不知道咋生成的,我只知道这货不能错,而且不同群是通用的。

好吧,打开后直接将参数中的 data.item 提取成一个 JS 数组:

var s = new Array;
s = [ "(此处省略数组内容)" ];

然后写个循环,提取非管理/创始人的QQ号码:

var qqs = new Array;    http:// 筛选后数据转存过来
for(var i=0;i<s.length;i++){
    if(!s[i].iscreator && !s[i].ismanager) qqs.push(s[i].uin);
}
qqs.join(' ');        http:// Chrome 的开发者工具会直接显示此结果

JavaScript只能帮到这了……,接下来得靠PHP了:

<?php
$qqs_1 = '群一 qqs.join(' ') 的值';
$qqs_2 = '群二 qqs.join(' ') 的值';
$qq1 = explode(' ', $qqs_1);
$qq2 = explode(' ', $qqs_2);
$result = '';
foreach($qq2 as $uin){
    if(in_array($uin, $qq1)) $result .= "{$uin}\r\n";
}
http:// 由于我是在命令行下运行,而CMD窗口复制太麻烦,所以直接输出成文件
file_put_contents('result.txt', $result);
?>

接下来,该咋处理咋处理了……

Typecho 修改固定链接后的SEO技巧

前两天将博客固定链接中最后的那个 id 换成了文章的缩略名,这下可惨了,搜索引擎们都得重新抓取一遍,我可懒得等他,当然,也怕给谷歌百度神马的降权了,于是有了这篇文章:

首先我的思路是通过 PHP 插入一段代码,识别到链接中最后一个参数为数字 id 则自动到数据库中查询并 301 到新地址。

于是问了问 Google 大哥,PHP 怎么获得伪静态的地址,这点问题对谷歌来说毫无压力——$_SERVER['ORIG_PATH_INFO']——就是他,然后便轮到正则了,由于是数字,这部分也很简单:.+\/([0-9]+)\.html

完成了,接下来的步骤便是用 PHP 将这堆东西整理起来:

- 阅读剩余部分 -