一,表的设计符合3NF,慢查询sql优化
1.1NF数据原子性,关系型数据库(例:mysql,sql server)都符合
2.2NF表中的记录是唯一的,通常设计一个主键来实现
3.3NF表中数据不要冗余,表的数据能够推导出来,就不应该单独一个字段
4.慢查询sql优化
#global:mysql启动开始的select情况[session|global]
show global status like 'com_select';
#显示慢查询次数
show global status like 'slow_queries';
#显示慢查询时间
show variables like 'long_query_time';
#设置慢查询时间
set long_query_time=1;
#配置my.ini慢查询日志文件
slow-query-log-file=/www/server/data/mysql-slow.log
#重启mysql开启慢查询
mysqld --safe-mode --slow-query-log
#通过explain 分析mysql如何执行sql语句
二,适当的索引(主键索引/唯一索引/全文索引/普通索引/外键索引/组合索引)
1.主键索引:必须为主键字段创建一个索引,这个索引就是所谓的”主索引”。主索引与唯一索引的唯一区别是:前者在定义时使用的关键字是 PRIMARY而不是UNIQUE。
#添加
#创建表时添加主键索引
create table aa(id int unsigned primary key auto_increment);
#创建后添加主键索引
create table aa(id int);
alter table aa add primary key(id);
2.唯一索引:它与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
#添加
#创建表时添加唯一索引
create table aa(id int unsigned unique);
#创建后添加唯一索引
create table aa(id int);
alter table aa add unique(id);
#查询
3.全文索引:文本字段上的普通索引只能加快对出现在字段内容最前面的字符串(也就是字段内容开头的字符)进行检索操作。如果字段里存放的是由几个、甚至是多个单词构成
的较大段文字,普通索引就没什么作用了。这种检索往往以LIKE %word%的形式出现,这对MySQL来说很复杂,如果需要处理的数据量很大,响应时间就会很长。
这类场合正是全文索引(full-text index)可以大显身手的地方。在生成这种类型的索引时,MySQL将把在文本中出现的所有单词创建为一份清单,查询操作将根据这份清单去检索有关的数
据记录。全文索引即可以随数据表一同创建,也可以等日后有必要时再使用下面这条命令添加:
ALTER TABLE tablename ADD FULLTEXT(column1, column2)
有了全文索引,就可以用SELECT查询命令去检索那些包含着一个或多个给定单词的数据记录了。下面是这类查询命令的基本语法:
SELECT * FROM tablename
WHERE MATCH(column1, column2) AGAINST(‘word1′, ‘word2′, ‘word3′)
上面这条命令将把column1和column2字段里有word1、word2和word3的数据记录全部查询出来。
注解:InnoDB数据表不支持全文索引。新版的MySQL5.6.24上InnoDB引擎也加入了全文索引,从MySQL 5.7开始支持中文全文索引,所以具体信息要随时关注官网
#添加
#创建表时添加全文索引
CREATE TABLE article (
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT(title, body)
) TYPE=MYISAM;
#alter table方式添加
ALTER TABLE `student` ADD FULLTEXT INDEX 索引名称 (`name`) #ft_stu_name是索引名,可以随便起
或者:ALTER TABLE `student` ADD FULLTEXT 索引名称 (`name`);
#create index方式添加
CREATE FULLTEXT INDEX 索引名称 ON `student` (`name`);
也可以在创建索引的时候指定索引的长度:
CREATE FULLTEXT INDEX 索引名称 ON `student` (`name`(20));
#使用方法:全文索引不能使用like "%fulltext%"
select * from student where match(name) agains('full');
4.普通索引:普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件(WHERE column = …)或排序条件(ORDER BY column)中的数据列创建索引。只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。
#添加
create table aa(id int unsigned);
create index id on aa(id);
5.组合索引:索引可以覆盖多个数据列,如像INDEX(columnA, columnB)索引。这种索引的特点是MySQL可以有选择地使用一个这样的索引。如果查询操作只需要用到columnA数据列上的一个索引,
就可以使 用组合索引INDEX(columnA, columnB)。不过,这种用法仅适用于在组合索引中排列在前的数据列组合。比如说,INDEX(A, B, C)可以当做A或(A, B)的索引来使用,但不能当做B、C或(B, C)的索引来使用。
#添加
alert table aa add INDEX `sindex` (`a`,`b`,`c`);
6.外键索引:一个表的主键索引是另一个表的字段
#创建表时添加全文索引
CREATE TABLE article (
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
tid VARCHAR(200)
FOREIGN KEY (tid) REFERENCES student (tid)
) TYPE=INNODB;
#alter table方式添加
ALTER TABLE article ADD FOREIGN KEY ids(tid) REFERENCES student (tid);
7.查询索引
desc aa;#不能显示索引名
show index from aa;#查询详细信息
show keys from aa; #查询详细信息
8.删除索引
#直接使用 drop index
DROP INDEX 索引名称 ON student;
#使用 alter table的方式
ALTER TABLE student DROP INDEX 索引名称;
9.index_type索引类型btree和hash的区别
在MySQL中,大多数索引(如 PRIMARY KEY,UNIQUE,INDEX和FULLTEXT)都是在BTREE中存储,但使用memory引擎可以选择BTREE索引或者HASH索引,两种不同类型的索引各自有其不同的使用范围。
Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引。
可能很多人又有疑问了,既然 Hash 索引的效率要比 B-Tree 高很多,为什么大家不都用 Hash 索引而还要使用 B-Tree 索引呢?任何事物都是有两面性的,Hash 索引也一样,虽然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也带来了很多限制和弊端,主要有以下这些。
(1)Hash 索引仅仅能满足”=”,”IN”和”<=>”查询,不能使用范围查询。
由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样。
(2)Hash 索引无法被用来避免数据的排序操作。
由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且Hash值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算;
(3)Hash 索引不能利用部分索引键查询。
对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。
(4)Hash 索引在任何时候都不能避免表扫描。
前面已经知道,Hash 索引是将索引键通过 Hash 运算之后,将 Hash运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。
(5)Hash 索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高。
对于选择性比较低的索引键,如果创建 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下。
10.索引的长度
在为CHAR和VARCHAR类型的数据列定义索引时,可以把索引的长度限制为一个给定的字符个数(这个数字必须小于这个字段所允许的最大字符个数)。这
么做的好处是可以生成一个尺寸比较小、检索速度却比较快的索引文件。在绝大多数应用里,数据库中的字符串数据大都以各种各样的名字为主,把索引的长度设置
为10~15个字符已经足以把搜索范围缩小到很少的几条数据记录了。
在为BLOB和TEXT类型的数据列创建索引时,必须对索引的长度做出限制;MySQL所允许的最大索引长度是255个字符。
11.添加索引的条件(在where中经常使用,字段内容重复率较低,字段内容变化频率较低)
#较频繁作为查询条件的字段应该创建索引,例如手机号码
#唯一性太差的字段不适合单独创建索引,例如男女
#更新非常频繁的字段不适合添加索引,例如金额
#不作为查询条件的字段不应创建索引
12.explain查看sql语句执行情况
id:1 #查询序列号
select_type:SIMPLE #查询类型
table:dept #查询的表名
partitions:NULL #表分区
type:ALL #扫瞄的方式,all全表扫描
possible_keys:NULL #可能使用到的索引
key:NULL #实际使用的索引
key_len:NULL #
ref:NULL #
rows:10 #该sql语句扫描了多少行,可能得到记录数
Extra:Using where #sql语句的额外信息,比如排序方式...
explain详解
https://www.cnblogs.com/galengao/p/5780958.html
13.索引使用注意事项
a.对于使用like的查询,查询如果是'%aaa' 不会使用到索引,'aaa%'会使用到索引。
b.如果条件中有or,那么使用的所有字段都必须建立索引。
d.如果列类型是字符串,那么条件中的数据要使用引号 '数据' ,否则不会使用索引。添加数据时字符串也必须使用引号'数据'。
c.如果mysql估计使用全表扫描要比使用索引快,则不会使用索引。
14.查看索引的使用情况
show status like 'Handler_read%';
Handler_read_key:这个值越高越好,越高表示使用索引查询到的次数
Handler_read_rnd_next:这个值越高,说明查询低效。
15.mysql小技巧
a.大批量导入数据时可以先禁用索引,减少创建索引的时间,提高数据导入效率
b.group by语句默认分组时,还会排序,可能会降低速度,添加order by null可以防止排序。
c.尽量使用join查询,因为使用join不需要在内存中创建临时表
d.选择合适的存储引擎
Myisam:如果一张表对事物要求不高,同事是以查询和添加为主的表,应该考虑使用mysiam,如BBS中的发帖表,回复表。
innodb:对事物要求高,保存的数据都是重要数据,应该考虑使用innodb,比如订单表,账号表。
Memory:数据变化非常频繁,不需要入库,同时又频繁的查询和修改,应该考虑使用mempry,比如信息配置,字段类型不支持text,重启mysql数据丢失
e.尽量使用定点数来存储数值,以保证数据的精确性
f.myisam如果经常删除修改记录,需要定期执行optimize table aa;对表进行碎片整理,否则会出现删除修改的数据无变化
g.备份数据库 mysqldump -uroot -p123456 数据库名称 > 文件路径,备份某些表 mysqldump -uroot -p123456 数据库名称 表名称 > 文件路径,恢复数据 source 文件路径
h.海量数据分页查询优化,order by使用索引字段。 select * from testsea where title like "左%" order by tid limit 90000,10;
三,分表
1.水平分割
分表维度:程序自定义,例:user0,user1,user2,根据用户的id%3查对应的表,一般需要一个辅助表来记录分表的用户id
分页查询:建立辅助表存储总记录数
2.垂直分割
四,主从复制
1.读写分离
2.多主,热备
五,存储过程
六,存储引擎的区别
Myisam innodb bdb memory archive
*批量插入速度 高 低 高 高 非常高
*事物安全 支持 支持
*全文索引 支持 5.6.4<
*锁机制 表锁 行锁 页锁 表锁 行锁
存储限制 无 64TB 无 有 无
B数索引 支持 支持 支持 支持
哈希索引 支持 支持
集群索引 支持
数据缓存 支持 支持
索引缓存 支持 支持 支持
数据可压缩 支持 支持
空间使用 低 高 低 N/A 非常低
内存使用 低 高 低 中等 低
支持外键 支持
七,表分区
八,搜索引擎Elasticsearch,sphinx
九,mysql原理
十,mysql自动优化设计
1.自动统计各表的sql语句
2.自动分析慢查询语句
3.根据sql语句自动优化
高并发数据库设计
1.获取表相关信息
a.查询user辅助表(memory引擎)对应的主从服务器,表不存在时自动创建新表
b.使用固定算法计算出对应的主从服务器,表不存在时自动创建新表
2.查询对应的主从服务器
user1->独立主从服务器
user2->独立主从服务器
user3->独立主从服务器
问题:
1.分表+分库能使用union联合查询吗
2.不能使用union联合查询,分页排序怎么处理