mysql什么分表?以及我什么知道该去哪个表取数据?
@大尨,这是你有性能问题的那个表吗
@大尨,我不了解啊,今天刚查的,我是数据库上手一两年的新手
@老虎会游泳 对我几个概念说几句后,我都马上怀疑我的想法了,典型的不熟悉
show table status like 'hu60_bbs_topic_content'
@大尨,哦好吧。那么根据 @无名啊 的计算,如果你能把有着大量实际内容的字段(比如extend)从这个表分离出去,就可以让表存储更多行的数据而不产生性能下降。
当然,创建正确的索引也很重要。我觉得创建一个 key uid_type(uid, type) 就足够了,是在大小和速度方面都平衡的选择。
key uid_type(uid, type)
@大尨,我们想看你的Avg_row_length(平均记录大小),以找到性能下降的真正原因。但是你并没有实际数据,所以确实没用。
Avg_row_length
@大尨,当然分表也是解决性能问题的好办法。而且减小平均记录大小只能优化一次,分表则是可扩展的,想优化几次就能优化几次。
鉴于你没有实际数据,我建议你用脚本创建一些测试数据用来实验,看看什么方法适合你。这样可能比理论分析更有说服力。
@大尨,如果你真的想优化count(*),就为变化程度最低(重复率最高)的某个字段创建一个索引。但是通常没有必要优化它吧,因为很少进行全表count(*)操作,通常的count(*)都是带条件的,你只需要为这个条件创建索引即可快速得到结果。
count(*)
@老虎会游泳,
如果你能把有着大量实际内容的字段(比如extend)从这个表分离出去,就可以让表存储更多行的数据而不产生性能下降
也不知@大尨 是否每次都要这个extend,若是的话,还是不用分离了吧,B+树多一层就多一层呗,比“再去查多一棵树来取得extend”好
extend
$count = DB::table("ulogs")->where("id",">",0)->count(); // SELECT COUNT(*) FROM `ulogs` WHERE id > 0
@老虎会游泳,@大尨,
当然分表也是解决性能问题的好办法。而且减小平均记录大小只能优化一次,分表则是可扩展的,想优化几次就能优化几次
确实,分表能大幅减少一个表的行数,应该作为主要手段?(毕竟有extend在,行记录的平均长度减不到哪儿去了)
@大尨,我觉得,看你取行数据时,是否经常也要用到extend?是的话,没必要拆表?
@大尨,举个例子,对于
$count = DB::table("ulogs")->where("uid","=",1)->count();
如果你在uid上有一个索引,那么可以瞬间得到结果。
但是对于
$count = DB::table("ulogs")->where("id",">",0)->count();
你在id上有索引(它是主键,主键是索引)也没用,这个索引太大了,所以还是得扫描很久。但是如果你在type字段上有索引,不加条件的话就能应用这个索引,反而更快。这就是“给不怎么变化的字段加索引可以优化count(*)”。
再举个例子,如果你有一个始终为0的字段,你给它加个索引,那应该就能立即获得全表count(*)的结果了,因为结果可以直接从这个索引里读取。
注意:没有必要为了优化count(*)而去专门添加一个不变的字段,不值得。
@老虎会游泳,自增主键的索引(即,聚簇索引?),应该算很小的索引了吧?
真的还会比这个快吗(tinyint字段啥的先排除)
@无名啊,让mysql自己告诉我们吧:
它选的不是key(id),而是key(topic_id),因为后者的变化比前者小多了(前者无重复,后者大量重复)。
@无名啊,我给变化更少的review创建索引之后:
review
create index review on hu60_bbs_topic_content(review)
它马上就改用review了,这个只有0、1、2三种取值,想统计数量很快就能得到结果。
@无名啊,不过它也不是特别智能。比如我给变化更少的access(只有0、1)创建索引,它就没有使用,还是继续使用key(topic_id)。看起来上面让它改用key(review)的原因是其key_len更小。但可以肯定的是,如果有其他索引,MySQL不会考虑使用主键,因为统计主键数量需要全表扫描。
access
key(topic_id)
key(review)
key_len
create index access on hu60_bbs_topic_content(access)
@大尨,这是你有性能问题的那个表吗
@大尨,我不了解啊,今天刚查的,我是数据库上手一两年的新手
@老虎会游泳 对我几个概念说几句后,我都马上怀疑我的想法了,典型的不熟悉
看这个数据好像也没啥用啊
@大尨,哦好吧。那么根据 @无名啊 的计算,如果你能把有着大量实际内容的字段(比如extend)从这个表分离出去,就可以让表存储更多行的数据而不产生性能下降。
当然,创建正确的索引也很重要。我觉得创建一个
key uid_type(uid, type)
就足够了,是在大小和速度方面都平衡的选择。@大尨,我们想看你的
Avg_row_length
(平均记录大小),以找到性能下降的真正原因。但是你并没有实际数据,所以确实没用。@大尨,当然分表也是解决性能问题的好办法。而且减小平均记录大小只能优化一次,分表则是可扩展的,想优化几次就能优化几次。
鉴于你没有实际数据,我建议你用脚本创建一些测试数据用来实验,看看什么方法适合你。这样可能比理论分析更有说服力。
@老虎会游泳,刚才我去查询了一个三百多万数据的表,InnoDB的count(*) 操作第一次查询挺慢的,第二次只会才会快一些这个,这个该什么优化?
@大尨,如果你真的想优化
count(*)
,就为变化程度最低(重复率最高)的某个字段创建一个索引。但是通常没有必要优化它吧,因为很少进行全表count(*)
操作,通常的count(*)
都是带条件的,你只需要为这个条件创建索引即可快速得到结果。@老虎会游泳,
也不知@大尨 是否每次都要这个
extend
,若是的话,还是不用分离了吧,B+树多一层就多一层呗,比“再去查多一棵树来取得extend
”好@老虎会游泳,@大尨,
确实,分表能大幅减少一个表的行数,应该作为主要手段?(毕竟有
extend
在,行记录的平均长度减不到哪儿去了)@大尨,我觉得,看你取行数据时,是否经常也要用到
extend
?是的话,没必要拆表?@大尨,举个例子,对于
如果你在uid上有一个索引,那么可以瞬间得到结果。
但是对于
你在id上有索引(它是主键,主键是索引)也没用,这个索引太大了,所以还是得扫描很久。但是如果你在type字段上有索引,不加条件的话就能应用这个索引,反而更快。这就是“给不怎么变化的字段加索引可以优化
count(*)
”。再举个例子,如果你有一个始终为0的字段,你给它加个索引,那应该就能立即获得全表
count(*)
的结果了,因为结果可以直接从这个索引里读取。注意:没有必要为了优化
count(*)
而去专门添加一个不变的字段,不值得。@老虎会游泳,自增主键的索引(即,聚簇索引?),应该算很小的索引了吧?
真的还会比这个快吗(tinyint字段啥的先排除)
@无名啊,让mysql自己告诉我们吧:
它选的不是key(id),而是key(topic_id),因为后者的变化比前者小多了(前者无重复,后者大量重复)。
@无名啊,我给变化更少的
review
创建索引之后:它马上就改用review了,这个只有0、1、2三种取值,想统计数量很快就能得到结果。
@无名啊,不过它也不是特别智能。比如我给变化更少的
access
(只有0、1)创建索引,它就没有使用,还是继续使用key(topic_id)
。看起来上面让它改用key(review)
的原因是其key_len
更小。但可以肯定的是,如果有其他索引,MySQL不会考虑使用主键,因为统计主键数量需要全表扫描。