各位亲爱的云友,
非常感谢大家踊跃参加DBA专家门诊一期:索引与sql优化,很多云友都提出了自己的问题,门诊主任医师玄惭对大家提的问题一一作了解答。现已整理好这些问题,分享在此,欢迎来拿,绝对干货! 篇幅较长,耐心细看!
我们将赠送每位提问者每人一本凌云杂志第四期,请各位以
论坛短消息形式将姓名、电话、地址发送给管理员xiaofanqie。
啊里新人(Q1):索引我一般都是只有主键,这玩意儿,是不是越少越好?
玄惭(A1):在日常的业务开发中,常见使用到索引的地方大概有两类:
第一类.做业务约束需求,比如需要保证表中每行的单个字段或者某几个组合字段是唯一的,则可以在表中创建唯一索引;
比如:需要保证test表中插入user_id字段的值不能出现重复,则在设计表的时候,就可以在表中user_id字段上创建一个唯一索引:
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`gmt_create` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_userid` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
第二类.提高SQL语句执行速度,可以根据SQL语句的查询条件在表中创建合适的索引,以此来提升SQL语句的执行速度;
此过程好比是去图书找一本书,最慢的方法就是从图书馆的每一层楼每一个书架一本本的找过去;快捷一点的方法就是先通过图书检索来确认这一本书在几楼那个书架上,然后直接去找就可以了;当然创建这个索引也需要有一定的代价,需要存储空间来存放,需要在数据行插入,更新,删除的时候维护索引:
例如:
CREATE TABLE `test_record` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`gmt_create` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5635996 DEFAULT CHARSET=utf8
该表有500w的记录,我需要查询20:00后插入的记录有多少条记录:
mysql> select count(*) from test_record where gmt_create>'2014-12-17 20:00:00';
+----------+
| count(*) |
+----------+
| 1 |
+----------+
1 row in set (1.31 sec)
可以看到查询耗费了1.31秒返回了1行记录,如果我们在gmt_create字段上添加索引:
mysql> alter table test_record add index ind_gmt_create(gmt_create);
Query OK, 0 rows affected (21.87 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select count(*) from test_record where gmt_create>'2014-12-17 20:00:00';
+----------+
| count(*) |
+----------+
| 1 |
+----------+
1 row in set (0.01 sec)
查询只消耗了0.01秒中就返回了记录.
总的来说,为SQL语句(select,update,delete)创建必要的索引是必须的,这样虽然有一定的性能和空间消耗,但是是值得,尤其是在大并发的请求下,大量的数据被扫描造成系统IO和CPU资源消耗完,进而导致整个数据库不可服务。
蓝雨麦浪(Q2):我想问个问题,怎么学好数据库,如果简单的sql,我会写。但是复杂了,就不知道怎么写了。其实也算是知道怎么写,但是就是理不清楚。不知道怎么优化。写出来也不知道是不是对的,对性能有没有什么影响之内的。还有就是,数据库的约束相关的比如外键之内的是使用数据库管理好还是程序控制好点。
玄惭(A2):怎么学好数据库是一个比较大题目,数据库不仅仅是写SQL那么简单,即使知道了SQL怎么写,还需要很清楚的知道这条SQL他大概扫描了多少数据,返回多少数据,是否需要创建索引。
至于SQL优化是一个比较专业的技术活,但是可以通过学习是可以掌握的,你可以把一条sql从执行不出来优化到瞬间完成执行,这个过程的成就感是信心满满的。
学习的方法可以有以下一些过程:
1、自己查资料,包括书本,在线文档,google,别人的总结等等,试图自己解决
2、多做实验,证明自己的想法以及判断
3、如果实在不行,再去论坛问,或者问朋友
4、如果问题解决了,把该问题的整个解决方法记录下来,以备后来的需要
5、多关注别人的问题,或许以后自己就遇到了,并总是试图去多帮助别人
6、习惯从多个方面去考虑问题,并且养成良好的总结习惯
下面是一些国内顶级数据库专家学习数据库的经验分享给大家:
http://www.eygle.com/archives/2005/08/ecinieoracleouo.html
其实学习任何东西都是一样,没有太多的捷径可走,必须打好了坚实的基础,才有可以在进一步学习中得到快速提高。
王国维在他的《人间词话》中曾经概括了为学的三种境界,我在这里套用一下:
古今之成大事业、大学问者,罔不经过三种之境界。
"昨夜西风凋碧树。独上高楼,望尽天涯路。"此第一境界也。
"衣带渐宽终不悔,为伊消得人憔悴。"此第二境界也。
"众里寻他千百度,蓦然回首,那人却在灯火阑珊处。"此第三境界也。
学习Oracle,这也是你必须经历的三种境界。
第一层境界是说,学习的路是漫漫的,你必须做好充分的思想准备,如果半途而废还不如不要开始。
这里,注意一个"尽"字,在开始学习的过程中,你必须充分阅读Oracle的基础文档,概念手册、管理手册、备份恢复手册等(这些你都可以在http://tahiti.oracle.com 上找到);OCP认证的教材也值得仔细阅读。打好基础之后你才具备了进一步提升的能力,万丈高楼都是由地而起。
第二层境界是说,尽管经历挫折、打击、灰心、沮丧,也都要坚持不放弃,具备了基础知识之后,你可以对自己感兴趣或者工作中遇到的问题进行深入的思考,由浅入深从来都不是轻而易举的,甚至很多时候你会感到自己停滞不前了,但是不要动摇,学习及理解上的突破也需要时间。
第三次境界是说,经历了那么多努力以后,你会发现,那苦苦思考的问题,那百思不得其解的算法原理,原来答案就在手边,你的思路豁然开朗,宛如拨云见月。这个时候,学习对你来说,不再是个难题,也许是种享受,也许成为艺术。
所以如果你想问我如何速成,那我是没有答案的。
不经一番寒彻骨,哪得梅花扑鼻香。
当然这三种境界在实际中也许是交叉的,在不断的学习中,不断有蓦然回首的收获。
我自己在学习的过程中,经常是采用"由点及面法"。
当遇到一个问题后,一定是深入下去,穷究根本,这样你会发现,一个简单的问题也必定会带起一大片的知识点,如果你能对很多问题进行深入思考和研 |