唯一索引(unique index)
强调唯一,就是索引值必须唯一。
create unique index [索引名] on 表名 (列名);
alter table 表名 add unique index [索引名] (列名);
删除索引:
drop index 索引名 on 表名;
alter table 表名 drop index 索引名;
主键
主键是一种特殊的唯一索引,主键要求建表时指定,一般用auto_increment列,关键字是primary key
creat table test2 (id int not null primary key auto_increment);
全文索引
InnoDB不支持,MyISAM支持性能比较好,一般在 CHAR、VARCHAR 或 TEXT 列上创建。
Create table 表名(
id int not null primary key anto_increment,
title varchar(100),FULLTEXT(title)
)type=MyISAM;
单列索引(普通索引)与多列索引(复合索引)
复合索引要注意"最左前缀原则"
"左前缀原则":在使用多列索引的时候 where中必须首先使用第一个索引(uname) 然后第二个(password) 第三个(..)
比如where uname="admin" and password="abc"
以下使用均起到到索引的效果:
where password="abc"
where password="abc" and uname="admin"
where uname="admin" or password="abc" (出现or则扫描全表)
create table test3 (
id int not null primary key auto_increment,
uname char(8) not null default '',
password char(12) not null,
INDEX(uname,password)
)type=MyISAM;
注意:INDEX(a, b, c)可以当做a或(a, b)的索引来使用,但不能当作b、c或(b,c)的索引来使用。这是一个最左前缀的 优化方法,在后面会有详细的介绍,你只要知道有这样两个概念。
聚簇索引
一种索引,该索引中键值的逻辑顺序决定了表中相应行的物理顺序。 聚簇索引确定表中数据的物理顺序。Mysql中MyISAM 表是没有聚簇索引的,innodb有(主键就是聚簇索引)
查看表索引
show index from tableName;
表数据类型选择
1.能小就用小。表数据类型第一个原则是:使用能正确的表示和存储数据的最短类型。这样可以减少对磁盘空间、内存、cpu缓存的使用。
2.避免用NULL,这个也是网上优化技术博文传的最多的一个。理由是额外增加字节,还有使索引,索引统计和值更复杂。很多还忽略一 个count(列)的问题,count(列)是不会统计列值为null的行数。
3.Tinyint、smallint、mediumint、int、bigint,分别需要8、16、24、32、64。
值域范围:-2 (n-1)~ 2 (n-1)-1
很多程序员在设计数据表的时候很习惯的用int,压根不考虑这个问题
笔者建议:能用tinyint的绝不用smallint
误区:int(1) 和int(11)是一样的,唯一区别是mysql客户端显示的时候显示多少位。
整形优先原则:能用整形的不用其他类型替换,如ip可以转换成整形保存,如商品价格‘50.00元’则保存成50
4.精确度与空间的转换。在存储相同数值范围的数据时,浮点数类型通常都会比DECIMAL类型使用更少的空间。FLOAT字段使用4 字节存储 数据。DOUBLE类型需要8 个字节并拥有更高的精确度和更大的数值范围,DECIMAL类型的数据将会转换成DOUBLE类型。
创建一个表:
create table one (
id smallint(10) not null auto_increment primary key,
username char(8) not null,
password char(4) not null,
`level` tinyint (1) default 0,
last_login char(15) not null,
index (username,password,last_login)
) engine=innodb;
分析sql语句执行情况:
explain 关键字
explain select * from one where last_login +1= 8388606 ; (错误用法)
explain select * from one where last_login = 8388607 ; (正确用法)
索引字段上使用表达式将失去索引效果
索引选择性
索引选择性是不重复的索引值也叫基数(cardinality)表中数据行数的比值,索引选择性=基数/数据行,基数可以通过 “show index from 表名”查看。高索引选择性的好处就是mysql查找匹配的时候可以过滤更多的行,唯一索引的选择性最佳,值为1。 那么对于非唯一索引或者说要被创建索引的列的数据内容很长,那就要选择索引前缀。这里就简单说明一下:
mysql> select count(distinct(username))/count(*) from one;
+------------------------------------+
| count(distinct(username))/count(*) |
+------------------------------------+
| 0.2047 |
+------------------------------------+
1 row in set (0.09 sec)
count(distinct(username))/count( )就是索引选择性,这里0.2太小了。假如username列数据很长,则可以通过 select count(distinct(concat(first_name, left(last_name, N))/count( ) from one;测试出接近1的索引选择性, 其中N是索引的长度,穷举法去找出N的值,然后再建索引。
系统配置与维护优化
重要的一些变量
key_buffer_size索引块缓存区大小, 针对MyISAM存储引擎,该值越大,性能越好.但是超过操作系统能承受的最大值,反而会使mysql变得不稳定. ----这是很重要的参数
sort_buffer_size 这是索引在排序缓冲区大小,若排序数据大小超过该值,则创建临时文件,注意和MyISAM_sort_buffer_size的区别----这是很重要的参数
read_rnd_buffer_size当排序后按排序后的顺序读取行时,则通过该缓冲区读取行,避免搜索硬盘。将该变量设置为较大的值可以大大改进ORDER BY的性能。但是,这是为每个客户端分配的缓冲区,因此你不应将全局变量设置为较大的值。相反,只为需要运行大查询的客户端更改会话变量
join_buffer_size用于表间关联(join)的缓存大小
tmp_table_size缓存表的大小
table_cache允许 MySQL 打开的表的最大个数,并且这些都cache在内存中
delay_key_write针对MyISAM存储引擎,延迟更新索引.意思是说,update记录时,先将数据up到磁盘,但不up索引,将索引存在内存里,当表关闭时,将内存索引,写到磁盘
optimize、Analyze、check、repair维护操作
optimize 数据在插入,更新,删除的时候难免一些数据迁移,分页,之后就出现一些碎片,久而久之碎片积累起来影响性能, 这就需要DBA定期的优化数据库减少碎片,这就通过optimize命令。如对MyISAM表操作:optimize table 表名
对于InnoDB表是不支持optimize操作,否则提示“Table does not support optimize, doing recreate + analyze instead”, 当然也可以通过命令:alter table one type=innodb; 来替代。
Analyze 用来分析和存储表的关键字的分布,使得系统获得准确的统计信息,影响 SQL 的执行计划的生成。对于数据基本没有发生 变化的表,是不需要经常进行表分析的。但是如果表的数据量变化很明显,用户感觉实际的执行计划和预期的执行计划不 同的时候, 执行一次表分析可能有助于产生预期的执行计划。Analyze table 表名
Check检查表或者视图是否存在错误,对 MyISAM 和 InnoDB 存储引擎的表有作用。对于 MyISAM 存储引擎的表进行表检查, 也会同时更新关键字统计数据
Repair optimize需要有足够的硬盘空间,否则可能会破坏表,导致不能操作,那就要用上repair,注意INNODB不支持repair操作
表结构的更新与维护
改表结构。当要在数据量千万级的数据表中使用alter更改表结构的时候,这是一个棘手问题。一种方法是在低并发低访问量的时 候用平常的alter更改表。另外一种就是建另一个与要修改的表,这个表除了要修改的结构属性外其他的和原表一模一样,这样就 能得到一个相应的.frm文件,然后用flush with read lock 锁定读,然后覆盖用新建的.frm文件覆盖原表的.frm, 最后unlock table 释放表。
建立新的索引。一般方法这里不说。
创建没索引的a表,导入数据形成.MYD文件。
创建包括索引b表,形成.FRM和.MYI文件
锁定读写
把b表的.FRM和.MYI文件改成a表名字
解锁
用repair创建索引。
这个方法对于大表也是很有效的。这也是为什么很多dba坚持说“先导数据库在建索引,这样效率更快”
定期检查mysql服务器 定期使用show status、show processlist等命令检查数据库。这里就不细说,这说起来也篇幅是比较大的,笔者对这个也不是很了解