mysql 单表字段多少合适_公司DBA关于MySQL开发的一点经验

尽量不要让数据库做过多运算

数据库主要是用来存储的,我们应避免让数据库做运算,比如写定时任务,存储过程等。复杂的计算应该在程序代码中实现。我们应该尽量简单的使用数据库。

控制数据量

一年内单表数据量一般含char不超过500W条,我们需要合理的分表。单个库的表建议在300到400之间。

单表字段数量

单表的字段应该少而精,那多少合适呢?一般单表字段上限控制在20到50个。

在开发中,我们要注意避免使用大SQL、大事务。

避免使用NULL字段

我发现很多童鞋在建表时喜欢字段默认NULL,使用NULL很难进行查询优化,我们如果对NULL列加索引,需要额外空间,而且含NULL的符合索引无效。

`a` char(32) DEFAULT NULL`b` int(10) NOT NULL

比如上面这种。

少用TEXT

我们可以使用VARCHAR代替TEXT,因为TEXT类型处理性能比VARCHAR要低,TEXT会强制生成临时表,从而浪费更多空间。UTF-8下,VARCHAR(65535)大概占用64K空间。

如果一定要使用,就拆成单独的一张表吧。

CREATE TABLE t1 (    id INT NOT NULL AUTO_INCREMENT,    data text NOT NULL,    PRIMARY KEY (id)) ENGINE=InnoDB;

关于索引

索引数量建议

索引虽然能改善查询,但如果索引列更新频繁,索引维护也会成为负担。我们如果不加索引就尽量不要加,最好不要超过字段数的20%。

关于函数运算

不要在索引列进行数学运算或者函数运算,因为这样会使索引失效。

-- 不要这样用select * from table WHERE to_days(current_date) – to_days(date_col) <= 10
-- 推荐使用select * from table WHERE date_col >= DATE_SUB('2011-10-22',INTERVAL 10 DAY);

自增列做主键

自增列做主键,有利于索引维护,并且主键不应该平繁修改。别用字符串做主键,比如不要使用UUID做主键。

推荐用独立块业务的AUTO_INCREMENT列或全局ID生成器做代理主键。

我们知道,InnoDB中,主键索引默认是以主键列创建的,那么问题来了。

如果没有指定主键,那么还会创建主键索引么?

尽量少使用外键

如果使用了外键,高并发下面容易产生死锁。我们应该由程序来保证约束。

SQL语句要简单

我看过好几百行的SQL,我认为这样不太好,一般一条SQL只能在一个CPU中运算,一条大SQL可能把数据库搞崩。

我们应该将大SQL拆成多条简单的小SQL,简单的SQL会使缓存命中率更高。

关于事务

我们应该尽量将与事务无关的操作放到事务外面,这样能减少锁资源的占用。

简单的使用

我们尽量少使用存储过程,触发器,尽量少用MySQL函数处理结果。数据的运算应该交由程序去操作。

关于SQL效率

改写OR为IN()

同一字段,将or改写为in()

  • OR效率:O(n)
  • IN 效率:O(Log n)
  • 当n很大时,OR会慢很多
Select * from table WHERE phone='12347856' or phone='42242233';-- 推荐使用inSelect * from table WHERE phone in ('12347856' , '42242233')

不同字段,将or改为union

Select * from table WHERE phone='010-88886666' or cellPhone='13800138000';-- 推荐使用 unionSelect * from table WHERE phone='010-88886666'unionSelect * from table WHERE cellPhone='13800138000';

用UNION ALL 而非 UNION

使用UNION会有去重开销。

关于JOIN

很多童鞋喜欢使用JOIN来连表查询,阿里巴巴开发手册里就建议不要超过三表的JOIN。

9c0657ccfe9570c4b03c22ce36fa0a7b.png

建议将表拆分。

Select * from tag JOIN tag_post on tag_post.tag_id=tag.id JOIN post on  tag_post.post_id=post.id WHERE tag.tag='二手玩具';

推荐这样做:

Select * from tag WHERE tag='二手玩具';Select * from tag_post WHERE tag_id=1321;Select * from post WHERE post.id in (123,456,314,141)

关于计数统计

  • 实时统计:用memcache,双向更新,凌晨跑基准
  • 非实时统计:尽量用单独统计表,定期重算

关于limit分页

我们平常可能写过这样的SQL:

Select * from table limit 10000,10;

但是这样会很慢,偏移量越大越慢。

我们推荐使用这样的方式

select * from table WHERE id>=23434 limit 11;

网上有人做了测试:

710d8374a51cbc866c4a45c378a9213f.png

不要在程序端对数据库显示加锁

“外部锁对数据库不可控高并发时是灾难极难调试和排查”

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值