rpmmysql
源码包linux
通用二进制redis
5.6-5.7sql
选择GA 6个月到1年之间的数据库
实例:缓存
mysqld在启动时,自动派生master thread ------>生成工做的线程(read write 资源管理 等线程)
预分配内存区域app
是SQL语言中,负责对数据库对象运行数据访问工做的指令集,以INSERT、UPDATE、DELETE三种指令为核心,分别表明插入、更新与删除,是开发以数据为中心的应用程序一定会使用到的指令,所以有不少开发人员都把加上SQL的SELECT语句的四大指令以“CRUD”来称呼运维
是用于描述数据库中要存储的现实世界实体的语言。socket
是数据库控制语言。是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句。在默认状态下,只有sysadmin,dbcreator,db_owner或db_securityadmin等人员才有权力执行DCelasticsearch
链接层:
一、提供链接协议(TCP/IP socket) 2、验证的功能 三、提供一个专门的链接线程(接收用户发来的SQL,执行完成以后返回最终结果,可是没有能力“看懂”SQL,会将SQL语句丢给下一层)
SQL层
1、接收上层发来语句 2、语法检查模块进行语法检查 3、语义的检查模块检查语义,分辨SQL语句的类型,将不一样种类的语句交给不一样的解析器。 4、解析器接收到SQL语句,进行解析操做,获得SQL的执行计划(explain) 5、优化器负责基于“成本”,找到消耗成本最低的执行计划。 6、执行器会基于优化器的选择,执行SQL语句,获得获取数据方法,交由下一层继续处理。 7、将二进制或者16进制数据,结构化成表 八、查询缓存:SQL语句的hash值+数据结果 ------>redis Tair(memcached)
存储引擎层
根据上层次获取数据的方法,把数据提取出来
系统:
定义?
用户名:密码
能作什么?
一、登陆系统
二、管理系统对象
MySQL 逻辑结构
数据库对象:
库 :用来存放表对象 建库-----> 进入库 ----> 表操做 表 : 原数据+数据行 二维表: 数据行+(列名字+列属性+多少行+占多大磁盘空间+权限)原数据
MySQL:
定义? 用户名@'主机范围' 主机范围被称之为白名单
主机范围:
10.0.0.200 oldboy.com 10.0.0.% -----》10.0.0.1-10.0.0.254 10.0.0.5% ----- 10.0.0.50-10.0.0.59 % XXXX no grant all privileges on *.* to app@'10.0.0.%' identified by '123';
开发申请用户时,提供给管理
app@'10.0.0.%' 密码: xxxx
权限
权限: ALL privileges SELECT, INSERT, UPDATE, DELETE, CREATE, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, DROP LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE
trigger
开发人员可能会用到的权限
create update insert select CREATE VIEW CREATE ROUTINE SHOW VIEW
CREATE TEMPORARY TABLES ALTER
语法:grant 权限 on 权限做用范围 to 用户 identified by '密码'
grant create,update,insert,select ,CREATE VIEW on bbs.* to bbsuser@'192.168.12.%' identified by '123';
select user,host,password from mysql.user;
开发人员申请用户流程:
一、IP段
二、用户名、密码要求
三、须要哪些权限
(1)建库? CREATE DATABASE db CHARSET utf8; 规范: 库名小写。 建库时加上CHARSET 字符集:utf8 utf8mb4 校对规则:默认都是大小写不敏感的。 lower_case_table_names=1
(2)删库?
DROP DATABASE db;
(3)修改库
ALTER DATABASE db CHARSET utf8mb4
Syntax: CREATE TABLE tbl_name (col_name column_definition,...) create_definition: col_name column_definition | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...) [index_option] ... | {INDEX|KEY} [index_name] [index_type] (index_col_name,...) [index_option] ... | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY] [index_name] [index_type] (index_col_name,...) [index_option] ... | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...) [index_option] ... | [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name,...) reference_definition | CHECK (expr) column_definition: data_type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [UNIQUE [KEY]] [[PRIMARY] KEY] [COMMENT 'string'] [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}] [STORAGE {DISK|MEMORY|DEFAULT}] [reference_definition] data_type: --------------------------------------------- | TINYINT[(length)] [UNSIGNED] [ZEROFILL] | INT[(length)] [UNSIGNED] [ZEROFILL] | BIGINT[(length)] [UNSIGNED] [ZEROFILL] | DATETIME[(fsp)] | CHAR[(length)] [CHARACTER SET charset_name] [COLLATE collation_name] | VARCHAR(length) | ENUM(value1,value2,value3,...) [CHARACTER SET charset_name] [COLLATE collation_name]
USE db; CREATE TABLE t1 ( id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '学生学号', NAME VARCHAR(30) NOT NULL COMMENT '学生姓名', gender ENUM ('m','f') NOT NULL DEFAULT 'm' COMMENT '学生性别', birthday DATETIME NOT NULL DEFAULT NOW() COMMENT '入学时间' ) ENGINE INNODB CHARSET utf8; -- 1.2.1 删除表 DROP TABLE t1; -- 1.2.3 修改表 -- (1)先添加手机号,内容非空(最后一列) ALTER TABLE t1 ADD telnum CHAR(11); -- int -2^31 ~ 2^31-1 -- bigint -2^63 ~ 2^63-1 -- (2)指定添加年龄列到name列后面的位置,示例以下: ALTER TABLE t1 ADD age TINYINT AFTER NAME; DESC t1; -- (3) 经过下面的命令在第一列添加sno字段。p200000001 ALTER TABLE t1 ADD sno CHAR(10) FIRST; -- (4)若要删除字段,可采用以下命令。 ALTER TABLE t1 DROP sno; -- (5)若要同时添加两个字段,可采用以下命令。 ALTER TABLE t1 ADD sage TINYINT FIRST,ADD qq VARCHAR(15); -- (6)修改字段类型的命令以下: ALTER TABLE t1 MODIFY NAME VARCHAR(20) ; -- (7)修改字段名称的命令以下: ALTER TABLE t1 CHANGE age oldboyage CHAR(4) ;
权限:
GRANT
REVOKE
INSERT INTO t1(id,NAME,age,...) UPDATE t1 SET xx=xx WHERE 1=1 DELETE FROM t1 WHERE id=100 -------------防止误删除,误修改------------- TRIGGER 触发器 ??? 防止无修改。 ------- 伪删除 —— UPDATE 替代 DELETE
链接 内链接: (1)传统链接 select a.id,b.xyz from a,b where a.id=b.id (2)自链接 NATURAL JOIN select a.id,b.xyz from a NATURAL JOIN b (3)join using(id) select a.id,b.xyz from a JOIN b using(id); (4) join on select a.id,b.xyz from a JOIN b on a.id=b.bid where (5) left join riht join select a.id,b.xyz from a left JOIN b on a.id=b.bid ------------------------ 表链接就是集合操做 内连接 where : select a.xxx,b.xxx from a,b where a.xxx=b.xxx and NATURAL JOIN : select a.xxx,b.xxx from a NATURAL JOIN b join using : select a.xxx,b.xxx from a JOIN b using(id) join on: 外链接 left join select a.xxx,b.xxx from a left JOIN b on a.xx=b.xxx and age>20 select * from student where id>10 select * from student where id=10 or id=20; select * from student where id in (10,20); #开发规范推荐使用union all 去条件查找 select * from student where id=10 union all select * from student where id=20
B树(默认): B+tree B*tree Hash 索引 fulltext 索引 B树: cluster indexes 汇集索引 辅助索引 ------>人为管控的:unique 普通的 index
普通索引的实战管理:
添加索引: use db alter table student add index idx_cid(classid); 查询索引: show index from student; desc student; 删除索引: alter table student drop key idx_cid;
主键索引建立
2.1.创建表时 CREATE TABLE `test` ( `id` int(4) NOT NULL AUTO_INCREMENT, `name` char(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8; create table t1(id int not null auto_increment primary key); 2.2.创建表后增长 CREATE TABLE `test1` ( `id` int(4) NOT NULL, `name` char(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=UTF8; 增长自增主键 alter table test1 change id id int(11) primary key not null auto_increment; 3、惟一索引 内容惟一,但不是主键。 alter table student add unique key uni_tel(telnum); 怎么判断某个列的值都是惟一的? 注意: 例子: 1、总行数查询 select count(*) from world.city; 2、基于某个列去重复以后还剩多少行 select count(distinct population) from world.city;
前缀索引和联合索引
4.1、前缀索引: 根据字段的前N个字符创建索引 alter table student add note varchar(200); alter table student add index idx_note(note(10)); 联合索引:多个字段创建一个索引。 where a女生 and b身高165 and c身材好 index(a,b,c) 特色:前缀生效特性。 alter table people add index idx(a,b,c); a,ab,abc,ac 能够走索引或部分走索引。 b bc c ca ba 不走索引。 ------------------------ create table people(id int not null auto_increment primary key , name varchar(20),gender enum('m','f'),shengao int,tizhong int); alter table people add index idx_gst(gender,shengao,tizhong);
获取优化器选择后的执行计划 mysql> explain select * from city where population <100\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: city type: range possible_keys: idx_popu key: idx_popu key_len: 4 ref: NULL rows: 1 Extra: Using index condition 1 row in set (0.00 sec) mysql> ++++++++++++++++++++++++++++ explain select SQL_NO_CACHE * from test where name='oldboy'\G SQL_NO_CACHE的做用是禁止缓存查询结果。 explain select name,gender,age from test where gender='F' and age <20; ------ 在MySQL中,查询数据总共两种方式:全表扫描、索引扫描 经过explain命令的type能够看到,ALL的话就是全表扫描。 mysql在使用全表扫描时的性能是极其差的,因此MySQL尽可能避免出现全表扫描 全表扫描何时出现? 1、业务确实要获取全部数据 2、不走索引,致使的全表扫描 2.1 没索引 2.2 索引建立有问题 2.3 语句有问题 索引扫描有不少种级别,也是经过explain type能看到 ------ type : 表示MySQL在表中找到所需行的方式,又称“访问类型” 常见类型以下: index, range, ref, eq_ref, const system, Null 从左到右,性能从最差到最好,咱们认为至少要达到range级别 1、index:Full Index Scan,index与ALL区别为index类型只遍历索引树 2、range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行。 显而易见的索引范围扫描是带有between或者where子句里带有<,>查询。 where条件后 > < >= <= in or between and 咱们在使用索引是,最低应当达到range use world; alter table city add index idx_popu(population); explain select * from city where population >5000000; explain select * from city where countrycode in ("CHN","JPN"); 当mysql使用索引去查找一系列值时,例如IN()和OR列表,也会显示range(范围扫描),固然性能上面是有差别的。 explain select * from test where countrycode in ('chn','jpn'); 改写为: explain select * from city where countrycode='chn' union select * from city where countrycode='jpn'; 3、ref:使用非惟一索引扫描或者惟一索引的前缀扫描,返回匹配某个单独值的记录行 explain select * from test where countrycode='chn'; 4、eq_ref:相似ref,区别就在使用的索引是惟一索引,对于每一个索引键值,表中只有一条记录匹配,简单来讲, 就是多表链接中使用primary key或者 unique key做为关联条件 A join B on A.sid=B.sid 5、const、system:当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。 如将主键置于where列表中,MySQL就能将该查询转换为一个常量 explain select * from city where id=1000; 6、NULL:MySQL在优化过程当中分解语句,执行时甚至不用访问表或索引, 例如从一个索引列里选取最小值能够经过单独索引查找完成。 mysql> explain select name,population from city; +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | 1 | SIMPLE | city | ALL | NULL | NULL | NULL | NULL | 4188 | NULL | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ Extra: Using temporary Using filesort Using join buffer 若是出现以上附加信息: 请检查order by ,group by ,distinct,join ,union 条件列上没有索引 explain select * from city where countrycode='CHN' order by population; 额外信息: key_len 越小越好 rows 越小越好
select count(distinct user) from mysql.user;
select count(distinct user,host) from mysql.user;
1、数据库索引的设计原则:
为了使索引的使用效率更高,在建立索引时,必须考虑在哪些字段上建立索引和建立什么类型的索引。
那么索引设计原则又是怎样的?
1.选择惟一性索引
惟一性索引的值是惟一的,能够更快速的经过该索引来肯定某条记录。
例如,学生表中学号是具备惟一性的字段。为该字段创建惟一性索引能够很快的肯定某个学生的信息。
若是使用姓名的话,可能存在同名现象,从而下降查询速度。
主键索引和惟一键索引,在查询中使用是效率最高的。
select count(*) from world.city;
select count(distinct countrycode) from world.city;
select count(distinct countrycode,population ) from world.city;
注意:若是重复值较多,能够考虑采用联合索引
2.为常常须要排序、分组和联合操做的字段创建索引
常常须要ORDER BY、GROUP BY、DISTINCT和UNION等操做的字段,排序操做会浪费不少时间。
若是为其创建索引,能够有效地避免排序操做。
3.为常做为查询条件的字段创建索引
若是某个字段常常用来作查询条件,那么该字段的查询速度会影响整个表的查询速度。所以,
为这样的字段创建索引,能够提升整个表的查询速度。
3.1 常常查询
3.2 列值的重复值少
注:若是常常做为条件的列,重复值特别多,能够创建联合索引。
4.尽可能使用前缀来索引
若是索引字段的值很长,最好使用值的前缀来索引。例如,TEXT和BLOG类型的字段,进行全文检索
会很浪费时间。若是只检索字段的前面的若干个字符,这样能够提升检索速度。
--------不走索引的状况(开发规范)
重点关注:
1) 没有查询条件,或者查询条件没有创建索引
select * from tab; 全表扫描。
select * from tab where 1=1;
(1)select * from tab;
SQL改写成如下语句:
selec * from tab order by price limit 10 须要在price列上创建索引
(2)
select * from tab where name='zhangsan' name列没有索引
改:
一、换成有索引的列做为查询条件
二、将name列创建索引
2) 查询结果集是原表中的大部分数据,应该是30%以上。
查询的结果集,超过了总数行数30%,优化器以为就没有必要走索引了。
假如:tab表 id,name id:1-100w ,id列有索引
select * from tab where id>500000;
若是业务容许,可使用limit控制。
怎么改写 ?
结合业务判断,有没有更好的方式。若是没有更好的改写方案
尽可能不要在mysql存放这个数据了。放到redis里面。
3) 索引自己失效,统计数据不真实
索引有自我维护的能力。
对于表内容变化比较频繁的状况下,有可能会出现索引失效。
4) 查询条件使用函数在索引列上,或者对索引列进行运算,运算包括(+,-,*,/,! 等)
例子:
错误的例子:select * from test where id-1=9;
正确的例子:select * from test where id=10;
5)隐式转换致使索引失效.这一点应当引发重视.也是开发中常常会犯的错误.
这样会致使索引失效. 错误的例子:
------------------------ mysql> alter table tab add index inx_tel(telnum); mysql> desc tab; +--------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | varchar(20) | YES | | NULL | | | telnum | varchar(20) | YES | MUL | NULL | | +--------+-------------+------+-----+---------+-------+ 3 rows in set (0.01 sec) mysql> select * from tab where telnum='1333333'; +------+------+---------+ | id | name | telnum | +------+------+---------+ | 1 | a | 1333333 | +------+------+---------+ 1 row in set (0.00 sec) mysql> select * from tab where telnum=1333333; +------+------+---------+ | id | name | telnum | +------+------+---------+ | 1 | a | 1333333 | +------+------+---------+ 1 row in set (0.00 sec) mysql> explain select * from tab where telnum='1333333'; +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ | 1 | SIMPLE | tab | ref | inx_tel | inx_tel | 63 | const | 1 | Using index condition | +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ 1 row in set (0.00 sec) mysql> explain select * from tab where telnum=1333333; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | tab | ALL | inx_tel | NULL | NULL | NULL | 2 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec) mysql> explain select * from tab where telnum=1555555; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | tab | ALL | inx_tel | NULL | NULL | NULL | 2 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec) mysql> explain select * from tab where telnum='1555555'; +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ | 1 | SIMPLE | tab | ref | inx_tel | inx_tel | 63 | const | 1 | Using index condition | +----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+ 1 row in set (0.00 sec) mysql> --------------------------------------- 6) <> ,not in 不走索引 EXPLAIN SELECT * FROM teltab WHERE telnum <> '110'; EXPLAIN SELECT * FROM teltab WHERE telnum NOT IN ('110','119'); ------------ mysql> select * from tab where telnum <> '1555555'; +------+------+---------+ | id | name | telnum | +------+------+---------+ | 1 | a | 1333333 | +------+------+---------+ 1 row in set (0.00 sec) mysql> explain select * from tab where telnum <> '1555555'; ----- 单独的>,<,in 有可能走,也有可能不走,和结果集有关,尽可能结合业务添加limit or或in 尽可能改为union EXPLAIN SELECT * FROM teltab WHERE telnum IN ('110','119'); 改写成: EXPLAIN SELECT * FROM teltab WHERE telnum='110' UNION ALL SELECT * FROM teltab WHERE telnum='119'
7) like "%_" 百分号在最前面不走
EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '31%' 走range索引扫描 EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '%110' 不走索引
%linux%类的搜索需求,可使用elasticsearch
8) 单独引用复合索引里非第一位置的索引列.
列子:
复合索引:
DROP TABLE t1 CREATE TABLE t1 (id INT,NAME VARCHAR(20),age INT ,sex ENUM('m','f'),money INT); ALTER TABLE t1 ADD INDEX t1_idx(money,age,sex); DESC t1 SHOW INDEX FROM t1
走索引的状况测试:
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30 AND sex='m'; EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30 ; EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND sex='m'; ----->部分走索引
不走索引的:
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=20 EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=30 AND sex='m'; EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE sex='m';