MySQL单表可以有多少条记录?
理论上来说,MySQL采用不同的存储引擎,例如MyISAM和InnoDB,每个表会有理论上的存储记录上限,可能取决于主键类型(比如采取bigint类型,最大到18446744073709551615),另外单个表也有存储大小上限(InnoDB限制参考https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html)。但这些理论上限可能还没达到,就达到了磁盘大小的限制或者操作系统文件大小等限制,比如一个表10个字段,平均每个字段64bytes,那么5000万条记录(甚至远未到int的上限)就可能需要占用空间641050000000/1024/1024/1024/=30GB,这些空间还不包含给这个表建立的索引等占用的空间,10个这样的表可能就远超300G磁盘空间了。
那么在实际应用中呢,网上常有的一个说法是MySQL 单表数据量大于 2000 万行,性能会明显下降。据说最早起源于百度。具体情况大概是这样的,当年的 DBA 测试 MySQL性能时发现,当单表的量在 2000 万行量级的时候,SQL 操作的性能急剧下降,阿里巴巴《Java 开发手册》提出单表行数超过 500 万行或者单表容量超过 2GB,就可以进行分库分表 。
一般来说MySQL 为了提高性能,会将表的索引装载到内存中。内存等资源足够的情况下,其能完成全加载进内存,查询不会有问题。但是当单表数据库到达某个量级的上限时,导致内存无法存储其索引,使得之后的 SQL 查询会产生磁盘 IO,从而导致性能下降。当然这个还可能与具体的表结构的设计有关。总之我们在实际应用过程中,可能需要根据应用的需求,在做好表设计的基础上,硬件资源充分利用的基础上,在数据库记录量达到千万级甚至数百万级别(500万),就可能需要考虑历史数据归档,或者分表分库了。这个数据量级别并不是 MySQL 数据库的限制,但数据量过大修改表结构,备份,恢复都可能有很大的问题。但是在项目开始阶段,不宜过度设计,立即使用分表分库设计。
MySQL单表多少个字段合适?
实际上MySQL自身本身也有理论上的限制,参考MySQL官方文档:https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html
但是在实际应用中,一种说法是控制单表字段数量 (1)单表字段数建议30左右,再多的话考虑垂直分表,一是冷热数据分离,二是大字段分离,三是常在一起使用的列尽可能放到一个表中。 (2)表字段控制少而精,可以提高IO效率,内存缓存更多有效数据,从而提高响应速度和并发能力,后续 alter table 也更快。
还有认为单张表多少个字段其实没有什么定论,但是表的单条记录的大小是有合理空间的,也就是需要根据具体硬件和操作系统来确定单条记录(row size)的大小:一般来说,现在硬盘的扇区大小都是4K(有些硬盘可以到16K),所以存储基于操作系统的MySQL单条记录的合理大小应不超过硬盘的扇区大小,如果超出意味着查找单条记录时需要多个磁盘扇区去查找,增加了寻道时间,单表数据量大了性能会下降。个人觉得设计表的时候,重点在于减少磁盘IO,提倡的一个原则是常在一起使用的列尽可能放到一个表中,这样可以避免较多的关联操作。尽量不要违背的一个原则是包含不必要的大字段,如果必须,则考虑下大字段分离,当字段涉及到text,blob及其以上的大字段时,查询操作可能会涉及到磁盘IO,从而降低性能。参考https://www.cnblogs.com/jpfss/p/10868988.html
MySQL单表可以建立多少个索引?
索引并不是越多越好,索引可以增加查询效率,但同样也会降低插入和更新的效率,甚至有些情况下会降低查询效率。因为 MySQL 优化器在选择如何优化查询时,会根据统一信息,对每一个可以用到的索引来进行评估,以生成出一个最好的执行计划,如果同时有很多个索引都可以用于查询,就会增加 MySQL 优化器生成执行计划的时间,同样会降低查询性能。另外索引对磁盘空间的占用也是成倍增加的
单张表的索引数量控制在5个以内,或不超过表字段个数的20%。索引建立应遵循的一个重要原则是:尽量建在选择性高的列上。 不在选择性低的列上建立索引,例如性别、类型。选择性计算方法如下:
Selectivity = Cardinality / Total Rows = select count(distinct col)/count(*) from tablename
Selectivity 越接近1说明col选择性越高,使用索引的过滤效果越好,如果结果小于0.2,则不建议在此列上创建索引,否则可能会拖慢SQL执行。
但有一种情况,idx_feedbackid_type (f_feedback_id,f_type),如果经常用 f_type=1 比较,而且能过滤掉90%行,那这个组合索引就值得创建。有时候同样的查询语句,由于条件取值不同导致使用不同的索引,也是这个道理。
参考网址:
https://bbs.huaweicloud.com/blogs/129395
https://segmentfault.com/a/1190000039899023
https://dev.mysql.com/doc/refman/8.0/en/optimization.html