1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-25 02:27:10 +08:00

Update MySQL.md

This commit is contained in:
SnailClimb 2019-06-18 10:52:59 +08:00
parent 734733aa18
commit 2458840865

View File

@ -1,12 +1,3 @@
<!-- TOC -->
- [书籍推荐](#书籍推荐)
- [文字教程推荐](#文字教程推荐)
- [视频教程推荐](#视频教程推荐)
- [常见问题总结](#常见问题总结)
<!-- /TOC -->
## 书籍推荐
- 《SQL基础教程第2版》 (入门级)
@ -14,100 +5,181 @@
## 文字教程推荐
[MySQL 教程(菜鸟教程)](http://www.runoob.com/mysql/mysql-tutorial.html)
[MySQL 教程(菜鸟教程)](http://www.runoob.com/MySQL/MySQL-tutorial.html)
[MySQL教程易百教程](https://www.yiibai.com/mysql/)
[MySQL教程易百教程](https://www.yiibai.com/MySQL/)
## 视频教程推荐
**基础入门:** [与MySQL的零距离接触-慕课网](https://www.imooc.com/learn/122)
**Mysql开发技巧:** [MySQL开发技巧](https://www.imooc.com/learn/398)  [MySQL开发技巧](https://www.imooc.com/learn/427)  [MySQL开发技巧](https://www.imooc.com/learn/449)
**MySQL开发技巧:** [MySQL开发技巧](https://www.imooc.com/learn/398)  [MySQL开发技巧](https://www.imooc.com/learn/427)  [MySQL开发技巧](https://www.imooc.com/learn/449)
**Mysql5.7新特性及相关优化技巧:** [MySQL5.7版本新特性](https://www.imooc.com/learn/533)  [性能优化之MySQL优化](https://www.imooc.com/learn/194)
**MySQL5.7新特性及相关优化技巧:** [MySQL5.7版本新特性](https://www.imooc.com/learn/533)  [性能优化之MySQL优化](https://www.imooc.com/learn/194)
[MySQL集群PXC入门](https://www.imooc.com/learn/993)  [MyCAT入门及应用](https://www.imooc.com/learn/951)
## 常见问题总结
- ### 存储引擎
### 存储引擎
[MySQL常见的两种存储引擎MyISAM与InnoDB的爱恨情仇](https://juejin.im/post/5b1685bef265da6e5c3c1c34)
#### 一些常用命令
- ### ②字符集及校对规则
**查看MySQL提供的所有存储引擎**
字符集指的是一种从二进制编码到某类字符符号的映射。校对规则则是指某种字符集下的排序规则。Mysql中每一种字符集都会对应一系列的校对规则。
Mysql采用的是类似继承的方式指定字符集的默认值每个数据库以及每张数据表都有自己的默认值他们逐层继承。比如某个库中所有表的默认字符集将是该数据库所指定的字符集这些表在没有指定字符集的情况下才会采用默认字符集 PS整理自《Java工程师修炼之道》
详细内容可以参考: [MySQL字符集及校对规则的理解](https://www.cnblogs.com/geaozhang/p/6724393.html#mysqlyuzifuji)
- ### ③索引相关的内容(数据库使用中非常关键的技术,合理正确的使用索引可以大大提高数据库的查询性能)
  Mysql索引使用的数据结构主要有**BTree索引** 和 **哈希索引** 。对于哈希索引来说底层的数据结构就是哈希表因此在绝大多数需求为单条记录查询的时候可以选择哈希索引查询性能最快其余大部分场景建议选择BTree索引。
  Mysql的BTree索引使用的是B数中的B+Tree但对于主要的两种存储引擎的实现方式是不同的。
  **MyISAM:** B+Tree叶节点的data域存放的是数据记录的地址。在索引检索的时候首先按照B+Tree搜索算法搜索索引如果指定的Key存在则取出其 data 域的值,然后以 data 域的值为地址读取相应的数据记录。这被称为“非聚簇索引”。
  **InnoDB:** 其数据文件本身就是索引文件。相比MyISAM索引文件和数据文件是分离的其表数据文件本身就是按B+Tree组织的一个索引结构树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键因此InnoDB表数据文件本身就是主索引。这被称为“聚簇索引或聚集索引”。而其余的索引都作为辅助索引辅助索引的data域存储相应记录主键的值而不是地址这也是和MyISAM不同的地方。**在根据主索引搜索时直接找到key所在的节点即可取出数据在根据辅助索引查找时则需要先取出主键的值再走一遍主索引。** **因此,在设计表的时候,不建议使用过长的字段作为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。** PS整理自《Java工程师修炼之道》
详细内容可以参考:
[干货mysql索引的数据结构](https://www.jianshu.com/p/1775b4ff123a)
[MySQL优化系列--索引的使用、原理和设计优化](https://blog.csdn.net/Jack__Frost/article/details/72571540)
[数据库两大神器【索引和锁】](https://juejin.im/post/5b55b842f265da0f9e589e79#comment)
- ### ④查询缓存的使用
my.cnf加入以下配置重启Mysql开启查询缓存
```sql
mysql> show engines;
```
![查看MySQL提供的所有存储引擎](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/mysql-engines.png)
从上图我们可以查看出 MySQL 当前默认的存储引擎是InnoDB,并且在5.7版本所有的存储引擎中只有 InnoDB 是事务性存储引擎,也就是说只有 InnoDB 支持事务。
**查看MySQL当前默认的存储引擎**
我们也可以通过下面的命令查看默认的存储引擎。
```sql
mysql> show variables like '%storage_engine%';
```
**查看表的存储引擎**
```sql
show table status like "table_name" ;
```
![查看表的存储引擎](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/查看表的存储引擎.png)
#### MyISAM和InnoDB区别
MyISAM是MySQL的默认数据库引擎5.5版之前。虽然性能极佳而且提供了大量的特性包括全文索引、压缩、空间函数等但MyISAM不支持事务和行级锁而且最大的缺陷就是崩溃后无法安全恢复。不过5.5版本之后MySQL引入了InnoDB事务性数据库引擎MySQL 5.5版本后默认的存储引擎为InnoDB。
大多数时候我们使用的都是 InnoDB 存储引擎,但是在某些情况下使用 MyISAM 也是合适的比如读密集的情况下。(如果你不介意 MyISAM 崩溃回复问题的话)。
**两者的对比:**
1. **是否支持行级锁** : MyISAM 只有表级锁(table-level locking)而InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。
2. **是否支持事务和崩溃后的安全恢复: MyISAM** 强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快但是不提供事务支持。但是**InnoDB** 提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。
3. **是否支持外键:** MyISAM不支持而InnoDB支持。
4. **是否支持MVCC** :仅 InnoDB 支持。应对高并发事务, MVCC比单纯的加锁更高效;MVCC只在 `READ COMMITTED``REPEATABLE READ` 两个隔离级别下工作;MVCC可以使用 乐观(optimistic)锁 和 悲观(pessimistic)锁来实现;各数据库中MVCC实现并不统一。推荐阅读[MySQL-InnoDB-MVCC多版本并发控制](https://segmentfault.com/a/1190000012650596)
5. ......
《MySQL高性能》上面有一句话这样写到:
> 不要轻易相信“MyISAM比InnoDB快”之类的经验之谈这个结论往往不是绝对的。在很多我们已知场景中InnoDB的速度都可以让MyISAM望尘莫及尤其是用到了聚簇索引或者需要访问的数据都可以放入内存的应用。
一般情况下我们选择 InnoDB 都是没有问题的但是某事情况下你并不在乎可扩展能力和并发能力也不需要事务支持也不在乎崩溃后的安全恢复问题的话选择MyISAM也是一个不错的选择。但是一般情况下我们都是需要考虑到这些问题的。
### 字符集及校对规则
字符集指的是一种从二进制编码到某类字符符号的映射。校对规则则是指某种字符集下的排序规则。MySQL中每一种字符集都会对应一系列的校对规则。
MySQL采用的是类似继承的方式指定字符集的默认值每个数据库以及每张数据表都有自己的默认值他们逐层继承。比如某个库中所有表的默认字符集将是该数据库所指定的字符集这些表在没有指定字符集的情况下才会采用默认字符集 PS整理自《Java工程师修炼之道》
详细内容可以参考: [MySQL字符集及校对规则的理解](https://www.cnblogs.com/geaozhang/p/6724393.html#MySQLyuzifuji)
### 索引
MySQL索引使用的数据结构主要有**BTree索引** 和 **哈希索引** 。对于哈希索引来说底层的数据结构就是哈希表因此在绝大多数需求为单条记录查询的时候可以选择哈希索引查询性能最快其余大部分场景建议选择BTree索引。
MySQL的BTree索引使用的是B数中的B+Tree但对于主要的两种存储引擎的实现方式是不同的。
- **MyISAM:** B+Tree叶节点的data域存放的是数据记录的地址。在索引检索的时候首先按照B+Tree搜索算法搜索索引如果指定的Key存在则取出其 data 域的值,然后以 data 域的值为地址读取相应的数据记录。这被称为“非聚簇索引”。
- **InnoDB:** 其数据文件本身就是索引文件。相比MyISAM索引文件和数据文件是分离的其表数据文件本身就是按B+Tree组织的一个索引结构树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键因此InnoDB表数据文件本身就是主索引。这被称为“聚簇索引或聚集索引”。而其余的索引都作为辅助索引辅助索引的data域存储相应记录主键的值而不是地址这也是和MyISAM不同的地方。**在根据主索引搜索时直接找到key所在的节点即可取出数据在根据辅助索引查找时则需要先取出主键的值再走一遍主索引。** **因此,在设计表的时候,不建议使用过长的字段作为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。** PS整理自《Java工程师修炼之道》
**更多关于索引的内容可以查看文档首页MySQL目录下关于索引的详细总结。**
### 查询缓存的使用
> 执行查询语句的时候会先查询缓存。不过MySQL 8.0 版本后移除,因为这个功能不太实用
my.cnf加入以下配置重启MySQL开启查询缓存
```properties
query_cache_type=1
query_cache_size=600000
```
Mysql执行以下命令也可以开启查询缓存
MySQL执行以下命令也可以开启查询缓存
```
```properties
set global query_cache_type=1;
set global query_cache_size=600000;
```
如上,**开启查询缓存后在同样的查询条件以及数据情况下,会直接在缓存中返回结果**。这里的查询条件包括查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的信息。因此任何两个查询在任何字符上的不同都会导致缓存不命中。此外如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、Mysql库中的系统表其查询结果也不会被缓存。
如上,**开启查询缓存后在同样的查询条件以及数据情况下,会直接在缓存中返回结果**。这里的查询条件包括查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的信息。因此任何两个查询在任何字符上的不同都会导致缓存不命中。此外如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、MySQL库中的系统表,其查询结果也不会被缓存。
缓存建立之后Mysql的查询缓存系统会跟踪查询中涉及的每张表如果这些表数据或结构发生变化那么和这张表相关的所有缓存数据都将失效。
缓存建立之后MySQL的查询缓存系统会跟踪查询中涉及的每张表,如果这些表(数据或结构)发生变化,那么和这张表相关的所有缓存数据都将失效。
**缓存虽然能够提升数据库的查询性能,但是缓存同时也带来了额外的开销,每次查询后都要做一次缓存操作,失效后还要销毁。** 因此开启缓存查询要谨慎尤其对于写密集的应用来说更是如此。如果开启要注意合理控制缓存空间大小一般来说其大小设置为几十MB比较合适。此外**还可以通过sql_cache和sql_no_cache来控制某个查询语句是否需要缓存**
```
```sql
select sql_no_cache count(*) from usr;
```
- ### ⑤事务机制
### 什么是事务?
**关系性数据库需要遵循ACID规则具体内容如下**
**事务是逻辑上的一组操作,要么都执行,要么都不执行。**
![事务的特性](https://user-gold-cdn.xitu.io/2018/5/20/1637b08b98619455?w=312&h=305&f=png&s=22430)
事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账1000元这个转账会涉及到两个关键操作就是将小明的余额减少1000元将小红的余额增加1000元。万一在这两个操作之间突然出现错误比如银行系统崩溃导致小明余额减少而小红的余额没有增加这样就不对了。事务就是保证这两个关键操作要么都成功要么都要失败。
### 事物的四大特性(ACID)
![事物的特性](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/事务特性.png)
1. **原子性:** 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
2. **一致性:** 执行事务前后,数据库从一个一致性状态转换到另一个一致性状态。
3. **隔离性:** 并发访问数据库时,一个用户的事物不被其他事务所干扰,各并发事务之间数据库是独立的;
2. **一致性:** 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
3. **隔离性:** 并发访问数据库时,一个用户的事不被其他事务所干扰,各并发事务之间数据库是独立的;
4. **持久性:** 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
**为了达到上述事务特性,数据库定义了几种不同的事务隔离级别:**
### 并发事务带来哪些问题?
- **READ_UNCOMMITTED未提交读:** 最低的隔离级别,允许读取尚未提交的数据变更,**可能会导致脏读、幻读或不可重复读**
- **READ_COMMITTED提交读:** 允许读取并发事务已经提交的数据,**可以阻止脏读,但是幻读或不可重复读仍有可能发生**
- **REPEATABLE_READ可重复读:** 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,**可以阻止脏读和不可重复读,但幻读仍有可能发生。**
- **SERIALIZABLE串行:** 最高的隔离级别完全服从ACID的隔离级别。所有的事务依次逐个执行这样事务之间就完全不可能产生干扰也就是说**该级别可以防止脏读、不可重复读以及幻读**。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对统一数据进行操作)。并发虽然是必须的,但可能会导致以下的问题。
这里需要注意的是:**Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.**
- **脏读Dirty read:** 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。
- **丢失修改Lost to modify:** 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如事务1读取某表中的数据A=20事务2也读取A=20事务1修改A=A-1事务2也修改A=A-1最终结果A=19事务1的修改被丢失。
- **不可重复读Unrepeatableread:** 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
- **幻读Phantom read:** 幻读与不可重复读类似。它发生在一个事务T1读取了几行数据接着另一个并发事务T2插入了一些数据时。在随后的查询中第一个事务T1就会发现多了一些原本不存在的记录就好像发生了幻觉一样所以称为幻读。
事务隔离机制的实现基于锁机制和并发调度。其中并发调度使用的是MVCC多版本并发控制通过行的创建时间和行的过期时间来支持并发一致性读和回滚等特性。
**不可重复度和幻读区别:**
详细内容可以参考: [可能是最漂亮的Spring事务管理详解](https://blog.csdn.net/qq_34337272/article/details/80394121)
不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。
### 事务隔离级别有哪些?MySQL的默认隔离级别是?
**SQL 标准定义了四个隔离级别:**
- **READ-UNCOMMITTED(读取未提交)** 最低的隔离级别,允许读取尚未提交的数据变更,**可能会导致脏读、幻读或不可重复读**。
- **READ-COMMITTED(读取已提交)** 允许读取并发事务已经提交的数据,**可以阻止脏读,但是幻读或不可重复读仍有可能发生**。
- **REPEATABLE-READ(可重复读)** 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,**可以阻止脏读和不可重复读,但幻读仍有可能发生**。
- **SERIALIZABLE(可串行化)** 最高的隔离级别完全服从ACID的隔离级别。所有的事务依次逐个执行这样事务之间就完全不可能产生干扰也就是说**该级别可以防止脏读、不可重复读以及幻读**。
------
| 隔离级别 | 脏读 | 不可重复读 | 幻影读 |
| :--------------: | :--: | :--------: | :----: |
| READ-UNCOMMITTED | √ | √ | √ |
| READ-COMMITTED | × | √ | √ |
| REPEATABLE-READ | × | × | √ |
| SERIALIZABLE | × | × | × |
MySQL InnoDB 存储引擎的默认支持的隔离级别是 **REPEATABLE-READ可重读**。我们可以通过`SELECT @@tx_isolation;`命令来查看
```sql
mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
```
这里需要注意的是:与 SQL 标准不同的地方在于 InnoDB 存储引擎在 **REPEATABLE-READ可重读**事务隔离级别下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以说InnoDB 存储引擎的默认支持的隔离级别是 **REPEATABLE-READ可重读** 已经可以完全保证事务的隔离性要求,即达到了 SQL标准的**SERIALIZABLE(可串行化)**隔离级别。
因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是**READ-COMMITTED(读取提交内容):**但是你要知道的是InnoDB 存储引擎默认使用 **REPEATABLE-READ可重读**并不会有任何性能损失。
InnoDB 存储引擎在 **分布式事务** 的情况下一般会用到**SERIALIZABLE(可串行化)**隔离级别。
### 锁机制与InnoDB锁算法
- ### ⑥锁机制与InnoDB锁算法
**MyISAM和InnoDB存储引擎使用的锁**
- MyISAM采用表级锁(table-level locking)。
@ -115,60 +187,74 @@
**表级锁和行级锁对比:**
- **表级锁:** Mysql中锁定 **粒度最大** 的一种锁对当前操作的整张表加锁实现简单资源消耗也比较少加锁快不会出现死锁。其锁定粒度最大触发锁冲突的概率最高并发度最低MyISAM和 InnoDB引擎都支持表级锁。
- **行级锁:** Mysql中锁定 **粒度最小** 的一种锁,只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。
- **表级锁:** MySQL中锁定 **粒度最大** 的一种锁对当前操作的整张表加锁实现简单资源消耗也比较少加锁快不会出现死锁。其锁定粒度最大触发锁冲突的概率最高并发度最低MyISAM和 InnoDB引擎都支持表级锁。
- **行级锁:** MySQL中锁定 **粒度最小** 的一种锁,只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。
详细内容可以参考:
[Mysql锁机制简单了解一下](https://blog.csdn.net/qq_34337272/article/details/80611486)
详细内容可以参考: MySQL锁机制简单了解一下[https://blog.csdn.net/qq_34337272/article/details/80611486](https://blog.csdn.net/qq_34337272/article/details/80611486)
**InnoDB存储引擎的锁的算法有三种**
- Record lock单个行记录上的锁
- Gap lock间隙锁锁定一个范围不包括记录本身
- Next-key lockrecord+gap 锁定一个范围,包含记录本身
**相关知识点:**
1. innodb对于行的查询使用next-key lock
2. Next-locking keying为了解决Phantom Problem幻读问题
3. 当查询的索引含有唯一属性时将next-key lock降级为record key
4. Gap锁设计的目的是为了阻止多个事务将记录插入到同一范围内而这会导致幻读问题的产生
5. 有两种方式显式关闭gap锁除了外键约束和唯一性检查外其余情况仅使用record lock A. 将事务隔离级别设置为RC B. 将参数innodb_locks_unsafe_for_binlog设置为1
- ### 大表优化
### 大表优化
当MySQL单表记录数过大时数据库的CRUD性能会明显下降一些常见的优化措施如下
1. **限定数据的范围:** 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内;
2. **读/写分离:** 经典的数据库拆分方案,主库负责写,从库负责读;
3 . **垂直分区:**
#### 1. 限定数据的范围
务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内;
#### 2. 读/写分离
经典的数据库拆分方案,主库负责写,从库负责读;
#### 3. 垂直分区
**根据数据库里面数据表的相关性进行拆分。** 例如,用户表中既有用户的登录信息又有用户的基本信息,可以将用户表拆分成两个单独的表,甚至放到单独的库做分库。
**简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。** 如下图所示,这样来说大家应该就更容易理解了。
![](https://user-gold-cdn.xitu.io/2018/6/16/164084354ba2e0fd?w=950&h=279&f=jpeg&s=26015)
![数据库垂直分区](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/数据库垂直分区.png)
**垂直拆分的优点:** 可以使得列数据变小在查询时减少读取的Block数减少I/O次数。此外垂直分区可以简化表的结构易于维护。
**垂直拆分的缺点:** 主键会出现冗余需要管理冗余列并会引起Join操作可以通过在应用层进行Join来解决。此外垂直分区会让事务变得更加复杂
4. **水平分区:**
- **垂直拆分的优点:** 可以使得列数据变小在查询时减少读取的Block数减少I/O次数。此外垂直分区可以简化表的结构易于维护。
- **垂直拆分的缺点:** 主键会出现冗余需要管理冗余列并会引起Join操作可以通过在应用层进行Join来解决。此外垂直分区会让事务变得更加复杂
#### 4. 水平分区
**保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。 水平拆分可以支撑非常大的数据量。**
水平拆分是指数据表行的拆分表的行数超过200万行时就会变慢这时可以把一张的表的数据拆成多张表来存放。举个例子我们可以将用户信息表拆分成多个用户信息表这样就可以避免单一表数据量过大对性能造成影响。
![数据库水平拆分](https://user-gold-cdn.xitu.io/2018/6/16/164084b7e9e423e3?w=690&h=271&f=jpeg&s=23119)
![数据库水平拆分](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/数据库水平拆分.png)
水平拆分可以支持非常大的数据量。需要注意的一点是分表仅仅是解决了单一表数据过大的问题但由于表的数据还是在同一台机器上其实对于提升MySQL并发能力没有什么意义所以 **水平拆分最好分库**
水平拆分能够 **支持非常大的数据量存储,应用端改造也少**,但 **分片事务难以解决** 跨节点Join性能较差逻辑复杂。《Java工程师修炼之道》的作者推荐 **尽量不要对数据进行分片,因为拆分会带来逻辑、部署、运维的各种复杂度** 一般的数据表在优化得当的情况下支撑千万以下的数据量是没有太大问题的。如果实在要分片尽量选择客户端分片架构这样可以减少一次和中间件的网络I/O。
**下面补充一下数据库分片的两种常见方案:**
- **客户端代理:** **分片逻辑在应用端封装在jar包中通过修改或者封装JDBC层来实现。** 当当网的 **Sharding-JDBC** 、阿里的TDDL是两种比较常用的实现。
- **中间件代理:** **在应用和数据中间加了一个代理层。分片逻辑统一维护在中间件服务中。** 我们现在谈的 **Mycat** 、360的Atlas、网易的DDB等等都是这种架构的实现。
详细内容可以参考: MySQL大表优化方案: [https://segmentfault.com/a/1190000006158186](https://segmentfault.com/a/1190000006158186)
详细内容可以参考:
[MySQL大表优化方案](https://segmentfault.com/a/1190000006158186)
### 一条SQL语句在MySQL中如何执行的
[一条SQL语句在MySQL中如何执行的](<https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485097&idx=1&sn=84c89da477b1338bdf3e9fcd65514ac1&chksm=cea24962f9d5c074d8d3ff1ab04ee8f0d6486e3d015cfd783503685986485c11738ccb542ba7&token=79317275&lang=zh_CN#rd>)
### MySQL高性能优化规范建议
[MySQL高性能优化规范建议](<https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485117&idx=1&sn=92361755b7c3de488b415ec4c5f46d73&chksm=cea24976f9d5c060babe50c3747616cce63df5d50947903a262704988143c2eeb4069ae45420&token=79317275&lang=zh_CN#rd>)
### 一条SQL语句执行得很慢的原因有哪些
[腾讯面试一条SQL语句执行得很慢的原因有哪些---不看后悔系列](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485185&idx=1&sn=66ef08b4ab6af5757792223a83fc0d45&chksm=cea248caf9d5c1dc72ec8a281ec16aa3ec3e8066dbb252e27362438a26c33fbe842b0e0adf47&token=79317275&lang=zh_CN#rd)