该段 Sql 分页代码能够优化吗?

2015-11-19 09:05:58 +08:00
 decdfgfe

代码如下
$sql="select id,second_level,third_level,title,description,update_time,thumb from p_ed2k where second_level='$cid' and third_level='$scid' order by id DESC limit $offset,$perNum";
分页越到后面越慢, second_level 和 third_level 已经做索引

1798 次点击
所在节点    数据库
31 条回复
xiamingchong
2015-11-19 09:08:10 +08:00
没有表结构怎么看,有联合索引么
decdfgfe
2015-11-19 09:11:36 +08:00
@xiamingchong
表结构如下
+--------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+----------------+
| id | int(7) | NO | PRI | NULL | auto_increment |
| page_id | int(7) | NO | | NULL | |
| page_url | varchar(50) | NO | | NULL | |
| second_level | varchar(50) | YES | MUL | NULL | |
| third_level | varchar(50) | YES | MUL | NULL | |
| title | varchar(500) | NO | | NULL | |
| resource | longtext | NO | | NULL | |
| description | text | YES | | NULL | |
| picture | varchar(1000) | YES | | NULL | |
| label | varchar(100) | YES | MUL | NULL | |
| size | varchar(20) | YES | | NULL | |
| read_count | int(11) | YES | | NULL | |
| is_finish | varchar(1) | YES | | NULL | |
| create_time | int(11) | YES | | NULL | |
| update_time | int(11) | YES | MUL | NULL | |
| resource_num | int(5) | YES | | NULL | |
| cover | varchar(100) | YES | | NULL | |
| thumb | varchar(100) | YES | | NULL | |
| status | tinyint(1) | NO | | 1 | |
| s_title | varchar(100) | YES | | NULL | |
| format | varchar(10) | YES | | NULL | |
+--------------+---------------+------+-----+---------+----------------+
msg7086
2015-11-19 09:14:11 +08:00
MySQL 分页本来就慢。先查出 id 列表然后用 id 去查记录吧。
loveyu
2015-11-19 09:15:30 +08:00
数据量多大
xiamingchong
2015-11-19 09:16:07 +08:00
@decdfgfe 最好是发创建表结构的语句,
还有多少数据就发现慢了?
msg7086
2015-11-19 09:18:14 +08:00
Rails 代码供参考

# MySQL hacks to improve pagination performance
@postids = Post.where(:category_id => @cat_id).paginate(:page => params[:page], :per_page => 15).order('id DESC').select('id').to_a;
@posts = Post.where(:id => @postids).order('id DESC');

比直接分页查数据快得多。
sheng9632
2015-11-19 09:18:41 +08:00
where id>$offset limit $pernum
decdfgfe
2015-11-19 09:19:28 +08:00
@loveyu 数据量只有 50 几 W 条。
inmyfree
2015-11-19 09:19:39 +08:00
我数据库比较挫,目前只想到两个东东,
1 、使用存储过程,可能会有一定的提升效果,但是可能不太明显
2 、应用层次做查找结果缓存,这样可以大大提升速度,缺点是数据更新可能会不及时
decdfgfe
2015-11-19 09:20:42 +08:00
@xiamingchong 在程序里面翻页时会很慢。
在 Mysql 里面 desc 执行时间却很快,本身服务器性能应该不会有这么大差别吧。
thinkmore
2015-11-19 09:51:25 +08:00
数据量大,翻页到中间就比较慢了
hpeng
2015-11-19 09:55:50 +08:00
既然 id 都排序了.你就记录上次查询的最后 id 嘛...然后就 id>lastId (个人理解
zyue
2015-11-19 09:59:43 +08:00
如果出现慢查询 econd_level 和 third_level 考虑加下索引
realpg
2015-11-19 10:03:17 +08:00
mysql limit 的 offset 比较大的情况下就会超慢……
自行用别的办法
superbear
2015-11-19 10:08:10 +08:00
@hpeng 正解,顺序翻页好使,但是一下翻到第 N 页就不太好弄。
superbear
2015-11-19 10:14:56 +08:00
可以查查 mysql 语句执行顺序, limit 是最后一步执行的
raysmond
2015-11-19 10:22:02 +08:00
建议把所有 id 放在内存中,可以用 redis/memcached ,分页的时候从内存中获取该页的所有 id ,然后再去数据库中查询
hpeng
2015-11-19 10:22:26 +08:00
@superbear 对噢。跳页就不行了。看来是个不好的方法
wmttom
2015-11-19 10:35:00 +08:00
percona 推荐的做法是查 id 分页,然后用查出来的主键 id join 本表来获取其他字段数据。
sujin190
2015-11-19 10:39:12 +08:00
翻页数据库在做操作时是数的,数据量大了肯定慢, explain 看啊

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/237210

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX