最近两天作需求,是要将退款和退货报表里使用的临时表改用固定表,html
本身建表时,如(只是举例):mysql
CREATE TABLE tasks ( task_id INT UNSIGNED NOT NULL AUTO_INCREMENT, parent_id INT UNSIGNED NOT NULL DEFAULT 0, task VARCHAR(100) NOT NULL, test_id INT UNSIGNED NOT NULL DEFAULT 0, date_added TIMESTAMP NOT NULL, date_completed TIMESTAMP, PRIMARY KEY (task_id), key parent_id(parent_id), key test_id (test_id ) )engine=INNODB;
像parent_id及test_id在连表查询时,屡次出如今where的条件中,因此要给他们加上索引。sql
在此过程当中,我想了这么几个问题:为何这里要用key而不用index呢?临时表有什么特色,它是存放在内存中吗?数据库
问题1.mysql中index和key的区别?session
---这种问题其实也是stackoverflow里的常见问题(http://stackoverflow.com/questions/1401572/what-are-differences-between-index-v-s-key-in-mysql)---post
key 是数据库的物理结构,处于模型层面的,它包含两层意义,一是约束(偏重于约束和规范数据库的结构完整性),二是索引(辅助查询用的)。包括primary key, unique key, foreign key 等。性能
->primary key 优化
两个做用,一是约束做用(constraint),用来规范一个存储主键和惟一性,但同时也在此key上创建了一个index;ui
->unique keyurl
两个做用,一是约束做用(constraint),规范数据的惟一性,但同时也在这个key上创建了一个index;
->foreign key
两个做用,一是约束做用(constraint),规范数据的引用完整性,但同时也在这个key上创建了一个index;
总结来讲:MySQL中的key是同时具备constraint和index的意义。
MySQL requires every Key also be indexed, that's an implementation detail specific to MySQL to improve performance.
index是数据库的物理结构,处于实现层面的,它只是辅助查询的,它建立时会在另外的表空间(mysql中的innodb表空间)以一个相似目录的结构存储。索引要分类的话,分为前缀索引、全文本索引等;所以,索引只是索引,它不会去约束索引的字段的行为(那是key要作的事情)。
Mysql常见索引有:主键索引、惟一索引、普通索引、全文索引、组合索引。
问题2.mysql中内存表和临时表的区别?
内存表:
1. 参数控制:max_heap_table_size=1024M。 2. 到达上线后报错,因此在同一时间须要足够的内存。 3. 表定义保存在磁盘上,数据和索引保存在内存里面。 4. 不能包含TEXT,BLOB等字段。 ------------------------------------------ 5.多个session,建立表的名字不能同样 6. 一个session建立会话后,对其余session也是可见的 7. data目录下只有tmp_memory.frm ,表结构放在磁盘上,数据放在内存中 8. mysql 重启或者关闭后内存表里的数据会丢失,可是表结构仍然存在 9. 能够建立索引,删除索引,支持惟一索引 10. 不影响主备,主库上插入的数据,备库也能够查到 11. show tables 看获得表
使用内存表需注意:
-> 内存表须要本身delete数据或者drop表;须要drop权限,这点比较危险
->内存表的表结构是保存在磁盘上的,若是多个session使用同一个表名,会存在冲突;若是不须要使用表名,若是使用一次都须要建立表结构,到时候会有不少小文件存在,不利于db的维护,dba清理表也有风险;
临时表:
1. 参数控制:tmp_table_size=1024M。 2. 到达上线后建立文件在磁盘上。 3. 表定义和数据都在内存里。 4. 能够包含TEXT, BLOB等字段。 ---------------------- 5. 建立的表的名字能够同样 6. 表结构和数据都放在内存中 7. 会话消失表结构和数据都消失 8. 能够建立索引,删除索引 9. 主库建立的表,备库查不到, 10. show tables 看不到表
另外:临时表和内存表的ENGINE 不一样,临时表默认的是MyISAM,而内存表是MEMORY
我想以前用临时表的考虑主要是下面两个特色:
-> 临时表是会话级别的,即便多个session建立的表名同样,都相互不影响
-> 会话消失,全部的都消失,这点很不利于应用排查问题
->不管内存表仍是临时表都须要消耗额外的内存空间,虽然db端能够忍受,可是不太可控;
->DB端还有这个参数:max_tmp_tables 一个客户能同时保持打开的临时表的最大数量,这个值默认32,能够根据须要调整此值
参考文章:mysql的内存表和临时表
问题3.MySQL单列索引和联合索引
有同事小伙伴说,根据须要与否,你能够考虑下联合索引。
“若是你对索引的理解不够,很常见的一个错误就是,为每一个列穿件独立的多音,或者按照错误的顺序建立多列索引。”
谈到索引策略,不少听到的诸如“把where条件里的列都建上索引”这样模糊的建议是很是错误的。这种方法最好的状况也只能是“一星”索引,
要实现真正更优的索引,得花精力优化索引列的顺序,或者建立一个全覆盖的索引。
---注:在《高性能MySQL》中文第三版提到了索引的评估:三星评估(three-star system)
索引将相关的记录放到一块儿得到一星;
若是索引中的数据顺序和查找中的排列顺序一致得到两星;
若是索引中的列包含了查询中须要的所有列则得到三星;
最近几天看《高性能MySQL》仍是收获挺大,勤看书仍是颇有必要的,同时和实践结合起来!
后续再来补充,若有我理解不正确的地方,但愿有人能提出!