索引及优化

MySQL

1、MySQL的架构总览

1

查询优化器 :MySQL会对我们的SQL语句进行优化;

存储引擎

  • InnoB:支持事务、行级锁、基于XA协议的分布式事务;适用于高并发场景(5.5的默认存储引擎)
  • MyISAM:不支持事务、表级锁;性能优先
查询数据库支持的存储引擎
show engines;

SQL优化

  • 原因:执行时间长、等待时间长、索引失效、参数设置不合理(缓冲区、线程数)
  • SQL优化主要是优化索引

索引

  • MySQL用来帮助高效查询的数据结构(B-Tree)

2、B-Tree和B+Tree

B-Tree (平衡多路查找树):可以显著减少定位记录时所经历的中间过程,从而加快存取速度

一个M阶的B-Tree具有的特性
    > 每个节点最多有m个孩子
    > 根节点的孩子数>=2(前提:树的高度大于一)
    > 除了根节点和叶子结点,其他节点的孩子数(ceil(m/2));向上取整
    > 所有的叶子结点都在一层
    > 各个结点包含n个关键字信息:(P0,K1,P1,K2,P2......Kn,Pn)
        其中
        - Ki(i=1,2......n)为关键字,且K(i-1)<Ki,即从小到大排序
        - 关键字的个数n必须满足:[ceil(m/2)-1,m-1]
        - Pi指向子树,且指针P(i-1)所指向的子树结点中所有关键字均小于Ki。即:父结点中任何关键字的左孩子都小于它,右孩子大于它

B-Tree示例图:

2

B+Tree :B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构,InnoDB存储引擎就是用B+Tree实现其索引结构

B+Tree相对于B-Tree有几点不同:

    非叶子节点只存储键值信息;
    所有叶子节点之间都有一个链指针;
    数据记录都存放在叶子节点中;

B+Tree示例图:


3、索引

1)单值索引

单列;一个表可以有多个单值索引

创建索引

-- 给users表的name属性创建索引
create index name_index on users(name) ;
alter table users add index name_index(name);

-- 查询索引
show index from users(表名);
-- 删除索引
drop index name_index(索引名) on users(表名);

2)唯一索引

单列;一个表只有一个唯一索引;主键默认唯一索引

-- 给users表的id属性创建索引
create unique index id_index on users(id) ;
alter table users add unique index id_index(id);

3)复合索引

多列;

-- 给users表的birthday,name属性创建索引
-- 先找birthday,如果birthday相同则再去name找
create index birthday_name_index on users(birthday,name) ;
alter table users add index birthday_name_index(birthday,name);

4)主键索引

主键索引不能为null,单值索引可以为null;

4、SQL执行计划

1)分析SQL执行计划

使用关键字explain ,分析分析SQL执行计划

mysql> explain select * from user;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL |    3 |       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+

2)准备数据

-- 建表准备数据
CREATE TABLE course(
  cid INT(2),
  cname VARCHAR(10),
  tid INT(2)
);
CREATE TABLE teacher(
  tid INT(2),
  tname VARCHAR(10),
  tcid INT(2)
);
CREATE TABLE teacher_card(
  tcid INT(2)teacher_card,
  tcdesc VARCHAR(10)
);

3)执行计划中的属性详解

可参考博客

-- 查询课程编号为2 或 教师证为3的老师
mysql> explain SELECT *
    -> FROM teacher t,course c, teacher_card tc
    -> WHERE t.tid=c.tid AND t.tcid= tc.tcid AND (c.cid=2 OR tc.tcid=3);
+----+-------------+-------+------
| id | select_type | table | ...
|  1 | SIMPLE      | t     | ...                         
|  1 | SIMPLE      | tc    | ... 
|  1 | SIMPLE      | c     | ... 

-- 在连接查询中,id值相同
-- t - tc - c 已知记录数顺序 3- 3- 4;==>执行顺序:记录数少的先执行;
-- 1- 查询产生的笛卡尔积
-- >  3 * 3 = 9 ;9 * 4 = 36
-- 2- 如果记录数多的先执行
-- >  4 * 3 = 12 ; 12  * 3= 36
-- 虽然最后的笛卡尔积数量不变,但是中间产生笛卡尔积数量不一样,第一种中间记录数少,占用的资源少;

-- 查询教英语的老师描述
mysql> EXPLAIN SELECT tc.tcdesc
    -> FROM teacher_card tc
    -> WHERE tc.tcid = (SELECT t.tcid FROM teacher t
    -> WHERE t.tid = (SELECT c.tid FROM course c WHERE c.cname = '英语'));
+----+-------------+-------+------+
| id | select_type | table | ...
|  1 | PRIMARY     | tc     | ... 
|  2 | SUBQUERY    | t    | ... 
|  3 | SUBQUERY    | c     | ... 

-- 在子查询中,id有 3-2-1 执行顺序 c-t-tc
-- 越内层的子查询,越先执行
  • id : id值相同 ,从上往下顺序执行 ;id值不同,从大到小顺序执行;

  • select_type

    • SIMPLE:简单查询(不包括连接查询,子查询)
    • PRIMARY :最外层的查询
    • SUNQUERY:非最外层查询
    • DERIVED:衍生查询(在查询的时候用到了临时表)
    • UNION RESULT:连接查询时产生的表
  • type

    SYSTEM>CONST> EQ_REF> REF>RANGE>IANDEX> ALL(要对type优化,前提是有索引)

    SYSTEM:只有一条数据的系统表、主查询的衍生表只有一条数据;(查询结果只有一条)

    -- 例如,这条SQL的主查询满足条件为system类型
    mysql>ALTER TABLE teacher ADD INDEX tid_index(tid);
    mysql> EXPLAIN SELECT *
        -> FROM (SELECT * FROM teacher t WHERE t.tid = 1) t_derived;
    +----+-------------+------------+--------+---------------+-----------+---------+------+--
    | id | select_type | table      | type   | possible_keys | key       | key_len | ref  | 
    +----+-------------+------------+--------+---------------+-----------+---------+------+---
    |  1 | PRIMARY     | <derived2> | system | NULL          | NULL      | NULL    | NULL |   
    |  2 | DERIVED     | t          | ref    | tid_index     | tid_index | 5       |      |   
    +----+-------------+------------+--------+---------------+-----------+---------+------+--

    CONST:在主键索引或唯一索引的情况下,只查询一条数据;(查询结果只有一条)

    mysql> ALTER TABLE teacher ADD PRIMARY KEY tid_primary(tid);
    -- 主键索引是tid,type是const
    mysql> EXPLAIN SELECT * FROM teacher t WHERE t.tid = 1;
    +----+-------------+-------+-------+-------------------+---------+---------+-------+------
    | id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows 
    +----+-------------+-------+-------+-------------------+---------+---------+-------+------
    |  1 | SIMPLE      | t     | const | PRIMARY,tid_index | PRIMARY | 4       | const |    1 
    +----+-------------+-------+-------+-------------------+---------+---------+-------+-----
    
    -- 查询tcid ,type 是 all
    mysql> EXPLAIN SELECT * FROM teacher t WHERE t.tcid = 1;
    +----+-------------+-------+------+---------------+------+---------+------+------+-------
    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra 
    +----+-------------+-------+------+---------------+------+---------+------+------+-------
    |  1 | SIMPLE      | t     | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using 
    +----+-------------+-------+------+---------------+------+---------+------+------+-------

    EQ_REF:唯一性索引; 对于每个索引键的查询,必须返回有且只有一条数据; (查询结果多条)

    -- 将列改为唯一性索引
    mysql> ALTER TABLE teacher ADD UNIQUE INDEX tcid_index(tcid);
    mysql> ALTER TABLE teacher_card ADD PRIMARY KEY tcid_primary(tcid);
    -- 此时teacher和teacher_card的数据条数为3
    -- 查询索引键,若两边数据条数一致(必须是唯一性索引)
    mysql> EXPLAIN SELECT t.tcid FROM teacher t,teacher_card tc WHERE t.tcid = tc.tcid;
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    | id | select_type | table | type   | possible_keys | key        | key_len | ref         
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    |  1 | SIMPLE      | t     | index  | tcid_index    | tcid_index | 5       | NULL         
    |  1 | SIMPLE      | tc    | eq_ref | PRIMARY       | PRIMARY    | 4       | mydb3.t.tcid 
    +----+-------------+-------+--------+---------------+------------+---------+-------------

    REF:非唯一性索引; 对于每个索引键的查询,返回n条数据(可以n=0);(查询结果多条)

    -- 给teacher添加一条数据
    -- 查询索引键,若两边数据条数不一致(可以为非唯一性索引)
    mysql> EXPLAIN SELECT t.tcid FROM teacher t,teacher_card tc WHERE t.tcid = tc.tcid;
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    | id | select_type | table | type   | possible_keys | key        | key_len | ref         
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    |  1 | SIMPLE      | t     | index  | tcid_index    | tcid_index | 5       | NULL         
    |  1 | SIMPLE      | tc    | ref    | PRIMARY       | PRIMARY    | 4       | mydb3.t.tcid 
    +----+-------------+-------+--------+---------------+------------+---------+-------------

    RANGE:检索指定范围的行的索引键 (关键字in有时候会失效);(查询结果多条)

    mysql> EXPLAIN SELECT t.tcid FROM teacher t WHERE t.tcid > 1;
    +----+-------------+-------+-------+---------------+------------+---------+------+------+-
    | id | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | 
    +----+-------------+-------+-------+---------------+------------+---------+------+------+-
    |  1 | SIMPLE      | t     | range | tcid_index    | tcid_index | 5       | NULL |    3 | 
    +----+-------------+-------+-------+---------------+------------+---------+------+------+-

    INDEX:查询数据的索引键;

    ALL:查询所有数据;

  • possible_keys:预测用到的索引(实际可能发生索引失效)

  • key:实际用到的索引

  • key_len :索引的计算长度

    # char和varchar类型key_len计算公式
    varchr(N)变长字段且允许NULL   =\
    N * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)+2(变长字段)
    varchr(N)变长字段且不允许NULL = \
    N * ( character set:utf8=3,gbk=2,latin1=1)+2(变长字段)
    char(N)固定字段且允许NULL = N * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)
    char(N)固定字段且允许NULL = N * ( character set:utf8=3,gbk=2,latin1=1)
    
    # 与数据类型长度无关
    # 数值数据的key_len计算公式:
    TINYINT允许NULL = 1 + 1(NULL)
    TINYINT不允许NULL = 1
    SMALLINT允许为NULL = 2+1(NULL)
    SMALLINT不允许为NULL = 2
    INT允许为NULL = 4+1(NULL)
    INT不允许为NULL = 4
    
    # 日期时间型的key_len计算:(针对mysql5.5)
    DATETIME允许为NULL = 8 + 1(NULL)
    DATETIME不允许为NULL = 8
    TIMESTAMP允许为NULL = 4 + 1(NULL)
    TIMESTAMP不允许为NULL = 4
  • ref:指明当前表参照的字段(null,const常量,参照的字段)

    -- tc 表参照了mydb3.t.tcid 字段
    mysql> EXPLAIN SELECT t.tcid FROM teacher t,teacher_card tc WHERE t.tcid = tc.tcid;
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    | id | select_type | table | type   | possible_keys | key        | key_len | ref         
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    |  1 | SIMPLE      | t     | index  | tcid_index    | tcid_index | 5       | NULL         
    |  1 | SIMPLE      | tc    | ref    | PRIMARY       | PRIMARY    | 4       | mydb3.t.tcid 
    +----+-------------+-------+--------+---------------+------------+---------+-------------
  • rows:实际查询的记录数

    mysql> EXPLAIN SELECT t.tcid FROM teacher_card tc,teacher t WHERE t.tcid = tc.tcid;
    
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    | id | select_type | table | type   | possible_keys | key        | key_len | ref         
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    |  1 | SIMPLE      | t     | index  | tcid_index    | tcid_index | 5       | NULL         
    |  1 | SIMPLE      | tc    | ref    | PRIMARY       | PRIMARY    | 4       | mydb3.t.tcid 
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    +------+--------------------------+
    | rows | Extra                    |
    +------+--------------------------+
    |    3 | Using index              |
    |    1 | Using where; Using index |
    +------+--------------------------+
    mysql> SELECT t.tcid FROM teacher_card tc,teacher t WHERE t.tcid = tc.tcid;
    +------+
    | tcid |
    +------+
    |    1 |
    |    2 |
    |    3 |
    +------+
  • extra

    • Using index,使用到索引
    • Using where,表示优化器需要通过索引回表查询数据;
  • Using filesort:无法利用索引来完成的排序

    -- 单列索引
    CREATE TABLE a(
      a INT,
      b INT,
      c INT,
      INDEX a_index(a),
      INDEX b_index(b),
      INDEX c_index(c)
    );
    -- 查询的 a 但是额外用b排了序,如果用a排序则不会出现Using filesort
    mysql> EXPLAIN SELECT * FROM a WHERE a='' ORDER BY b;
    +------+--------------------------+
    | rows | Extra                    |
    +------+--------------------------+
    |    1 | Using where; Using filesort |
    +------+--------------------------+
    
    -- 复合索引 不能跨列 要满足最佳左前缀,否则出现Using filesort
    DROP INDEX a_index ON a;
    DROP INDEX b_index ON a;
    DROP INDEX c_index ON a;
    ALTER TABLE a ADD INDEX a_b_c_index(a,b,c);
    -- 满足最佳左前缀,没有跨列
    mysql> EXPLAIN SELECT * FROM a WHERE a='' ORDER BY b;
    +------+--------------------------+
    | rows | Extra                    |
    +------+--------------------------+
    |    1 | Using where; Using index |
    +------+--------------------------+
    -- 跨列
    mysql> EXPLAIN SELECT * FROM a WHERE a='' ORDER BY c;
    +------+--------------------------+
    | rows | Extra                    |
    +------+--------------------------+
    |    1 | Using where; Using index; Using filesort |
    +------+--------------------------+
    -- 不满足最佳左前缀
    mysql>EXPLAIN SELECT * FROM a WHERE b='' ORDER BY c;
    +------+--------------------------+
    | rows | Extra                    |
    +------+--------------------------+
    |    1 | Using where; Using index; Using filesort |
    +------+--------------------------+

    (补充: 回表查询:指的是在索引中没有要查询的数据,需要回到表中查询)

5、优化示例

1)单表优化

-- 单表优化
-- 创建表
CREATE TABLE book(
  bid INT NOT NULL PRIMARY KEY,
  NAME VARCHAR(20),
  authorid INT NOT NULL,
  publicid INT NOT NULL,
  typeid INT NOT NULL
);
-- 查询authorID=1,typeid=2或3的 bid
mysql> EXPLAIN SELECT bid FROM book WHERE typeid IN (2,3) AND authorid = 1 ORDER BY typeid DESC;
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows |                   |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
|  1 | SIMPLE      | book  | ALL  | NULL          | NULL | NULL    | NULL |    5 | 
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+
 Extra
------------------+
 Using where; Using filesort
------------------+
-- 优化 1 添加索引,(消除了Using filesort,提高了type等级index)
ALTER TABLE book ADD INDEX b_t_a_index(bid,typeid,authorid);
mysql> EXPLAIN SELECT bid FROM book WHERE typeid IN (2,3) AND authorid = 1 ORDER BY typeid DESC;
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows |                   |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
|  1 | SIMPLE      | book  | index  | NULL        | NULL |   12    | NULL |    5 | 
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
------------------+
 Extra
------------------+
 Using where; Using index;Using filesort
------------------+
-- 优化2 
-- 修改索引顺序(提高了type等级 ref)
-- 含IN 的查询放到后面,避免可能的失效
ALTER TABLE book ADD INDEX atb_index(authorid,typeid,bid); 
mysql> EXPLAIN SELECT bid FROM book WHERE authorid = 1 AND typeid IN (2,3) ORDER BY typeid DESC;
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----
| id | select_type | table | type | possible_keys | key       | key_len | ref   | rows | 
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----
|  1 | SIMPLE      | book  | ref  | atb_index     | atb_index | 4       | const |    2 | 
+----+-------------+-------+------+---------------+-----------+---------+-------+------+--------------------------+
Extra                    |
---------------------+
Using where; Using index |
---------------------+

2)多表优化

EXPLAIN SELECT * FROM teacher t , course c  WHERE t.tid = c.tid AND c.cname = '语文';
-- 或者
EXPLAIN SELECT * FROM teacher t LEFT JOIN  course c ON t.tid = c.tid WHERE c.cname = '语文';
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows |           
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
|  1 | SIMPLE      | t     | ALL  | NULL          | NULL | NULL    | NULL |    3 |           
|  1 | SIMPLE      | c     | ALL  | NULL          | NULL | NULL    | NULL |    4 | 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+
Extra     
--------------------+
Using where; Using join buffer |
--------------------+

-- 优化 1 添加索引 
-- 给哪张表添加索引 --> 满足原则"小表驱动大表";
--                --> 索引经常使用,不常改变

3)避免索引失效原则

  • 复合索引需要满足最佳左前缀;
  • 复合索引尽量使用全索引匹配;
  • 复合索引不能使用(不等于、和 IS NULL);
  • 索引上不要进行一些运算操作;
  • 范围查询是不使用关键字IN;
  • 模糊查询尽量以"常量"开头不以"%"开头;
  • 不要使用OR;
  • 不要使用字段的类型转换;

4)常见的优化方法

  • IN和EXIST的使用:

    • 如果主查询的数据很大,用IN
    • 如果子查询的数据很大,用EXIST
  • order by 的使用

    Using filesort 分为双路排序[1扫描排序字段,2扫描其它字段]、单路排序[扫描全度字段](根据磁盘IO次数)

    可以通过切换排序方法和增大排序使用的buffer大小

    保证排序的一致性

  • 避免使用SELECT *

5) 慢查询日志

记录mysql中超过阀值(long query time)默认10秒;

-- 查看慢查询日志是否开启
show variables like "%slow_query_log%";
-- 临时开启
set globle slow_query_log = 1;
-- 永久开启
-- 修改mysql的配置文件
-- slow_query_log = 1
-- slow_query_log_file = /var/mysql/slow.log    制定一个路径寻访日志

-- 查看阀值大小
show variables like "%long_query_time%";
-- 临时设置大小(重启生效)
set globle long_query_time = 时长(s);
-- 永久设置大小(重启生效)
-- 修改mysql的配置文件
-- long_query_time = 时长

-- 查询超过阀值的SQL 
show globle status like "%slow_queris%"; -- 数量

-- mysql的工具,查看慢日志记录
mysqldumpslow

6、分析数据

1)使用profiles

分析执行SQL的在各环节的执行时间

-- 查看执行SQL的时间和query_id
show profiles
-- 
show variables like "%profiling%";
-- 开启profiling属性
set profiling = on;
-- 分析执行SQL的在各环节的执行时间
show profile all for query 1; -- 1是查出来的query_id

2)使用全局日志

可以记录所有执行的SQL

-- 查看是否开启全局日志
show variables like "%general_log%";
-- 开启全局日志,记录到mysql.general_log表中
set globle general_log = 1;
set globle log_output = 'table';

7、锁机制

解决资源共享造成的并发问题 参考[mydddfly]博客

  • 读锁(共享锁):读操作,一个资源可以被多个访问读取;
  • 写锁(互斥锁):写操作,一个资源在进行写操作时,独占;

1)MySQL的锁机制

开销 加锁速度 死锁 粒度 并发性能
行级锁 不会死锁 大(锁冲突概率高)
表级锁 会出现死锁 小(锁冲突概率低)
页面锁 会出现死锁

2)存储引擎使用的锁

  • INNODB:默认使用行级锁,也支持表级锁
  • MyISAM:默认使用表级锁
  • MEMORY:默认使用表级锁

3)表锁

MySQL的表级锁有两种模式:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁;

-- 通过检查table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定争夺情况;
-- 值越大争夺越严重
mysql> show status like 'table%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Table_locks_immediate | 46    |
| Table_locks_waited    | 0     |
+-----------------------+-------+

如何给表加锁

-- lock table 表名 read/write  给表加上读/写锁
mysql> lock table teacher read;
-- 查看表是否使用锁
mysql> show open tables;
+--------------------+----------------------------------------------+--------+-------------+
| Database           | Table                                        | In_use | Name_locked |
+--------------------+----------------------------------------------+--------+-------------+
| mysql              | time_zone_transition_type                    |      0 |           0 |
| mydb3              | teacher                                      |      1 |           0 |
+--------------------+----------------------------------------------+--------+-------------+

4)行锁

  • InnoDB实现了以下两种类型的行锁。
    • 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁
    • 排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁
    • 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁
    • 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁

(为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁)

  • 如何给行加锁
-- 可以通过检查InnoDB_row_lock状态变量来分析系统上的行锁的争夺情况:
show status like 'innodb_row_lock%';
Show innodb status;

-- 共享锁
select * from teacher where tid = 1 lock in share mode;
-- 排它锁
select * from teacher where tid = 1 for update;

8、主从复制

博文看考

1)mysql 的主从复制原理


MySQL之间数据复制的基础是二进制日志文件(binary log file)。一台MySQL数据库一旦启用二进制日志后,其作为master,它的数据库中所有操作都会以“事件”的方式记录在二进制日志中,其他数据库作为slave通过一个I/O线程与主服务器保持通信,并监控master的二进制日志文件的变化,如果发现master二进制日志文件发生变化,则会把变化复制到自己的中继日志中,然后slave的一个SQL线程会把相关的“事件”执行到自己的数据库中,以此实现从数据库和主数据库的一致性,也就实现了主从复制;

2)实现主从复制

主服务器配置

-- 修改配置文件
[mysqld]
log-bin = mysql-bin
server-id = 1
-- 创建用户并授权
mysql> CREATE USER 'flynn'@'localhost' IDENTIFIED BY '123456';#创建用户
mysql> GRANT REPLICATION SLAVE ON *.* TO 'flynn'@'localhost';#分配权限
mysql>flush privileges;   #刷新权限
-- 查看master状态,记录二进制文件名和位置:
show master status;

从服务器配置、

-- 配置文件
server-id = 2

-- 重启mysql,打开mysql会话,执行同步SQL语句
mysql> CHANGE MASTER TO
    ->     MASTER_HOST='',
    ->     MASTER_USER='',
    ->     MASTER_PASSWORD='',
    ->     MASTER_LOG_FILE='二进制文件名',
    ->     MASTER_LOG_POS='位置';
    
-- 启动slave 同步
mysql> start slave;
-- 查看状态
mysql> show slave status

对主服务器配置约束

[mysqld]
# 不同步哪些数据库  
binlog-ignore-db = ''  
  
# 只同步哪些数据库,除此之外,其他不同步  
binlog-do-db = '' 

9、思考

1)为什么索引是默认是B-Tree,而不是hash、二叉树、红黑树

  • hash:可以快速定位但是没有顺序IO复杂度高
  • 二叉树:树的高度不均匀,不能自平衡,存储的数据越大则树的高度越高,IO代价越高
  • 红黑树:存储的数据越大则树的高度越高,IO代价越高

2)为什么建议使用自增长的主键作为索引

自增的主键是连续的在插入过程中尽量减少页分裂,即使进行页分裂,也只会分裂很少的一部分。并且能减少数据的移动,每次插入都是插入到最后。总之就是减少分裂和移动的频率

猜你喜欢

转载自www.cnblogs.com/f1ynn/p/11471069.html