一个数据库优化问题

时间:2022-12-11 17:59:22
一个系统通过用户ID从数据库中查询信息进行登录,当用户信息表数据量很大(已经影响到登录性能的状态),请问有什么优化策略,已知只有少量一部分用户会经常访问系统。

29 个解决方案

#1


我的第一想法是加索引

#2


这种情况很适合加层redis缓存,经常登录的会逐渐缓存起来

#3


缓存和索引都要有,避免全表扫描同时也降低访问数据库的次数。

#4


 加上数据库读写分离。

#5


一般可从索引、事务、缓存、无锁查询、分表、表分区之类考虑。你这个表述上看,数据相当大了,QQ是按QQ号划分管理

#6


根据用户分区或者分表把,用缓存会带来用户更改信息要及时更新缓存

#7


在特殊字段上面建立索引,会增加查询效率!

#8


索引应该不用考虑,你这id肯定是主键。我想问的是你这用户表到底有多大,主键访问一个用户会影响到登录性能。
1、首先看看你的表是不是InnoDB引擎,不是的话查询是很慢的,我当时MyISAM 引擎,100W数据单库单表1-3S。
2、表设计上,拆分基本用户表,包含几个基础信息,比如username、password、mobile、email等,后面也可做用户中心。
3、从表设计上,改动比较大,加缓存,登录之后取用户缓存就行了。(缓存只是减少别的操作访问数据库,登录这里只能直接查数据库)
4、还有就是读写分离、分库、分表了。

#9


使用内存数据库,可以加快访问速度,呵呵

#10


可以根据时间条件加索引(我相信已经有了),查询的时候分两部分,
1.select * from table where update>? and userId=? 这样可以查询几天内的活跃用户,扫的数据很少
2.如果查不到,再查原始的数据。

#11


引用 2 楼 autfish 的回复:
这种情况很适合加层redis缓存,经常登录的会逐渐缓存起来


与他的想法类似,但是可以做一点点变化。
启动的时候,默认把经常登录或者最近有登录的缓存。。每次登录默认去缓存取,没有再去数据库取,取到以后再缓存。。

#12


取数据的时候可以做redis缓存,保存常登录用户信息
另外,类似中国移动手机号登录的,可以分库分表存储数据

#13


这种 场景提升最明显的是冷热分离,1个月内登陆次数超过1次的用户复制到0级活跃用户表,1年内登陆过超过1次的用户拆到1级活跃用户表,0级用户表建到内存上,1级用户表建到Lucene,然后用户登陆过程为-内存表-Lucene检索-数据库。

#14


缓存是要用的  10楼的建议也很棒!

引用 10 楼 zhuweisyyc 的回复:
可以根据时间条件加索引(我相信已经有了),查询的时候分两部分,
1.select * from table where update>? and userId=? 这样可以查询几天内的活跃用户,扫的数据很少
2.如果查不到,再查原始的数据。

#15


引用 2 楼 autfish 的回复:
这种情况很适合加层redis缓存,经常登录的会逐渐缓存起来
 缓存登陆加索引查询

#16


针对楼主只有少量用户访问的话。只是登录比较慢的话。

 1.读写分离。显然这种情况不合适,这种设计到了数据库集群,要加数据库服务器,分一个主服务器和多个从服务器,还要运维配置,成本太高。显然不合适。
 2. 优化sql语句。select * from table where update>? and userId=? 这样可以查询几天内的活跃用户,扫的数据很少。这种方法还是可行的。
 3. 加redis或Memcached缓存,效果比较好,成本比较低,可以尝试一下。

#17


还是上贴一下大概的数据结构和数据量吧,如果数据量没有巨大,单表访问的话一般在ID列建索引就可以解决了。
如果是有多张表还做了连接查询,要看到表之间的关联设计和索引情况,才能给出合理建议。

#18


1.用户id如果目前不是索引的话,加上索引应该可以解决。
2.用户id已经时索引的情况,数据多到按主键索引查询依然很慢的话,那就直接缓存+分表吧
   redis将每次登陆的用户信息缓存一段时间自动过期(如一个月)
   用户表按id进行模运算,分成若干子表(如模,就有n张子表,用户表数据量能减少n倍)

#19


有多少数据呢?数据量都大到影响登录了,不是应该把登录迁移到ldap上更合适?

#20


个人观点
弄两个表;最后加一个登录时间;最近一个月登录的放在一个表里面;超过的移除
这样就行了   第一次来最近的表查询,没有去第二个;oracle的话可以考虑分区等

#21


引用 13 楼 HinanaiTenshi 的回复:
这种 场景提升最明显的是冷热分离,1个月内登陆次数超过1次的用户复制到0级活跃用户表,1年内登陆过超过1次的用户拆到1级活跃用户表,0级用户表建到内存上,1级用户表建到Lucene,然后用户登陆过程为-内存表-Lucene检索-数据库。
一个数据库优化问题

#22


一年半以前的帖子你们还在挖坟。。。

#23


[yabao=][/yabao] 一个数据库优化问题

#24


缓存技术和索引技术。

话说现在CSDN的广告和博客推荐太多了,打开页面比以前乱很多啊!!

#25


使用ldap这种目录服务器,专门用于登录

#26


解决思路:
1、数据库方面:读写分离,分库分表,添加索引,如果要使用中间件的话,建议使用阿里的drds完全可以解决数据量大的问题
2、sql优化:where条件跟上添加索引的字段,避免全表或则全库检索
3、服务处理:做切面操作,让我们DML操作走master库,DQL走slave库读数据,为保持原子性,最好添加缓存策略,做到业务端透明
4、检索引擎:查询走solr或者elasticsearch库,全文检索引擎的查询速率是非常快的,因为库里的每个字段都添加了索引,可以解决查询pending,timeout的问题,同样要注意在同步数据的过程中延迟的问题

#27


加个缓存,encache这种轻量级的框架还是挺好用的

#28


一年半以前的帖子你们还在挖坟。。。

#29


通用的做法是 session走缓存

#1


我的第一想法是加索引

#2


这种情况很适合加层redis缓存,经常登录的会逐渐缓存起来

#3


缓存和索引都要有,避免全表扫描同时也降低访问数据库的次数。

#4


 加上数据库读写分离。

#5


一般可从索引、事务、缓存、无锁查询、分表、表分区之类考虑。你这个表述上看,数据相当大了,QQ是按QQ号划分管理

#6


根据用户分区或者分表把,用缓存会带来用户更改信息要及时更新缓存

#7


在特殊字段上面建立索引,会增加查询效率!

#8


索引应该不用考虑,你这id肯定是主键。我想问的是你这用户表到底有多大,主键访问一个用户会影响到登录性能。
1、首先看看你的表是不是InnoDB引擎,不是的话查询是很慢的,我当时MyISAM 引擎,100W数据单库单表1-3S。
2、表设计上,拆分基本用户表,包含几个基础信息,比如username、password、mobile、email等,后面也可做用户中心。
3、从表设计上,改动比较大,加缓存,登录之后取用户缓存就行了。(缓存只是减少别的操作访问数据库,登录这里只能直接查数据库)
4、还有就是读写分离、分库、分表了。

#9


使用内存数据库,可以加快访问速度,呵呵

#10


可以根据时间条件加索引(我相信已经有了),查询的时候分两部分,
1.select * from table where update>? and userId=? 这样可以查询几天内的活跃用户,扫的数据很少
2.如果查不到,再查原始的数据。

#11


引用 2 楼 autfish 的回复:
这种情况很适合加层redis缓存,经常登录的会逐渐缓存起来


与他的想法类似,但是可以做一点点变化。
启动的时候,默认把经常登录或者最近有登录的缓存。。每次登录默认去缓存取,没有再去数据库取,取到以后再缓存。。

#12


取数据的时候可以做redis缓存,保存常登录用户信息
另外,类似中国移动手机号登录的,可以分库分表存储数据

#13


这种 场景提升最明显的是冷热分离,1个月内登陆次数超过1次的用户复制到0级活跃用户表,1年内登陆过超过1次的用户拆到1级活跃用户表,0级用户表建到内存上,1级用户表建到Lucene,然后用户登陆过程为-内存表-Lucene检索-数据库。

#14


缓存是要用的  10楼的建议也很棒!

引用 10 楼 zhuweisyyc 的回复:
可以根据时间条件加索引(我相信已经有了),查询的时候分两部分,
1.select * from table where update>? and userId=? 这样可以查询几天内的活跃用户,扫的数据很少
2.如果查不到,再查原始的数据。

#15


引用 2 楼 autfish 的回复:
这种情况很适合加层redis缓存,经常登录的会逐渐缓存起来
 缓存登陆加索引查询

#16


针对楼主只有少量用户访问的话。只是登录比较慢的话。

 1.读写分离。显然这种情况不合适,这种设计到了数据库集群,要加数据库服务器,分一个主服务器和多个从服务器,还要运维配置,成本太高。显然不合适。
 2. 优化sql语句。select * from table where update>? and userId=? 这样可以查询几天内的活跃用户,扫的数据很少。这种方法还是可行的。
 3. 加redis或Memcached缓存,效果比较好,成本比较低,可以尝试一下。

#17


还是上贴一下大概的数据结构和数据量吧,如果数据量没有巨大,单表访问的话一般在ID列建索引就可以解决了。
如果是有多张表还做了连接查询,要看到表之间的关联设计和索引情况,才能给出合理建议。

#18


1.用户id如果目前不是索引的话,加上索引应该可以解决。
2.用户id已经时索引的情况,数据多到按主键索引查询依然很慢的话,那就直接缓存+分表吧
   redis将每次登陆的用户信息缓存一段时间自动过期(如一个月)
   用户表按id进行模运算,分成若干子表(如模,就有n张子表,用户表数据量能减少n倍)

#19


有多少数据呢?数据量都大到影响登录了,不是应该把登录迁移到ldap上更合适?

#20


个人观点
弄两个表;最后加一个登录时间;最近一个月登录的放在一个表里面;超过的移除
这样就行了   第一次来最近的表查询,没有去第二个;oracle的话可以考虑分区等

#21


引用 13 楼 HinanaiTenshi 的回复:
这种 场景提升最明显的是冷热分离,1个月内登陆次数超过1次的用户复制到0级活跃用户表,1年内登陆过超过1次的用户拆到1级活跃用户表,0级用户表建到内存上,1级用户表建到Lucene,然后用户登陆过程为-内存表-Lucene检索-数据库。
一个数据库优化问题

#22


一年半以前的帖子你们还在挖坟。。。

#23


[yabao=][/yabao] 一个数据库优化问题

#24


缓存技术和索引技术。

话说现在CSDN的广告和博客推荐太多了,打开页面比以前乱很多啊!!

#25


使用ldap这种目录服务器,专门用于登录

#26


解决思路:
1、数据库方面:读写分离,分库分表,添加索引,如果要使用中间件的话,建议使用阿里的drds完全可以解决数据量大的问题
2、sql优化:where条件跟上添加索引的字段,避免全表或则全库检索
3、服务处理:做切面操作,让我们DML操作走master库,DQL走slave库读数据,为保持原子性,最好添加缓存策略,做到业务端透明
4、检索引擎:查询走solr或者elasticsearch库,全文检索引擎的查询速率是非常快的,因为库里的每个字段都添加了索引,可以解决查询pending,timeout的问题,同样要注意在同步数据的过程中延迟的问题

#27


加个缓存,encache这种轻量级的框架还是挺好用的

#28


一年半以前的帖子你们还在挖坟。。。

#29


通用的做法是 session走缓存