比如我有一张 post,它本应该包含的字段(text 类型的 body 已被移出到附表):
id、user_id、title、description、num_views、num_likes、num_comments、create_time
这时候我要取 posts 列表:
SELECT `id` FROM `post` ORDER BY `id` DESC LIMIT 10000, 20
SELECT * FROM `post` WHERE `id` IN (上一步foreach出的ids)
我的问题:
1、上面的读取方式是不是比单纯的 SELECT * FROM post ORDER BY id DESC LIMIT 10000, 20 效率要更高?如果是这样,那随着表记录越来越庞大,是不是把 id 独立出去能够获得更快的 LIMIT 速度?
2、抛开主从/Cache等等其它因素,单纯的读库,因为三个 num_* 字段相对来讲 update 是比较频繁的(特别是 num_views 每次打开文章页都会触发更新),这个 update 和我的 LIMIT 读取是不是在锁机制上存在着排队和竞争?那如果这样,我把这个三个字段独立出去是不是能够增加并发程度(LIMIT 不受 update 的困扰,毕竟 title 和 description 的更新几率要小的多)?
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
1、覆盖索引查询的确会比普通的limit start,N 方式要好一些。具体的可以实测下,根据我的经验可以增加不少
2、大量update的确会对表造成一些影响。不过不建议大量拆表,这样虽然可以降低写的压力。但是代码结构可能维护起来就很灾难了。毕竟不可能无限进行分表。。建议前面加一层cache。redis or memcache。 数据id_key 进行incr操作,达到某个值进行同步到数据库。比如rand(5,10)。这样数据库压力可以降低很多,效率也可以进行保证。代码维护也没有很复杂。
提升数据库查询的速度首先应考虑建议索引和优化索引方面的努力,在数据量级较小的情况下,通过索引查询的差别其实是非常低的,如果这时候就拆表,加上程序上重新合并多表查询所消耗的时间,未必就真的比单表少。而拆表主要还是针对百万、千万级以上的表,在有索引的情况下都会比较吃力的时候进行的。
更新和读取的锁问题,如果较大且更新频繁的表,建议采用
InnoDB引擎进行行锁。设计数据库尽量符合三大范式,考虑一下