image.png

通常和zerofill一起使用,比如int(3),存入1,则自动填充为001。并不是存入的长度


image.png

image.png

image.png

char(n),varchar(n)中的n是最大长度。


image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png



image.png

image.png

image.png

外键索引一般不用,可以通过业务逻辑来实现。全文索引一般也不用,直接上全文搜索引擎:sphinx、elasticsearch


表索引的创建原则:

  1. 最适合素银的列是出现在where子句中的列,或连接子句中的列而不是出现在select关键字后的列

  2. 索引列的基数越大,索引的效果越好

  3. 对字符串进行索引,应该制定一个前缀长度,可以节省大量的索引空间

  4. 根据情况创建符合索引,符合索引可以提高查询效率

  5. 避免创建过多索引,索引会二维占用磁盘空间,降低写操作效率

  6. 主键尽量选择较短的数据类型,可以有效减少索引的磁盘占用,调高查询效率


为什么复合/多列索引更高效呢?

比如key('章','节','段'),它不是分别创建若干个索引,而是创建一个索引,作用在这个索引的组合上。缩短查询范围:如果只查某章,则扫描整个某章;若查询某章下的某节,则把某章下的某节扫描一遍。


对于where name like "%wang%"类型的查询,如果前面有%,则name的索引会失效。这种情况最好用全文搜索引擎,如:sphinx、elasticsearch



索引的注意事项:

  1. 符合索引遵循前缀原则

  2. like查询,%不能放在前面,可以使用全文索引来实现类似功能

  3. column is null 可以使用索引

  4. 如果mysql估计使用索引比全表扫描更慢,会放弃使用索引

  5. 如果or前的条件中的列有索引,后面的没有,索引都不会被用到

  6. 列类型是字符串,查询一定要给值加引号,否则索引失效

(比如字段类型是varchar,where name="100"索引有效,where name=100索引无效)



image.png

答案1:

    update A,B set A.c1=B.c1,A.c2=B.c2 where A.id=B.id and B.age>50

答案2:

    update A inner join B on A.id=B.id set A.c1=B.c1,A.c2=B.c2  where B.age>50



image.png

交叉连接会产生笛卡尔积,不用。

image.png

image.png

左外连接以左表为准,右外连接以右表为准,内连接(inner join)只以on后面的条件为准。

image.png

image.png



image.png

首先要找到查询速度慢的原因。然后优化查询过程中的数据访问,优化长难的查询语句,优化特定类型的查询语句。

        查询速度慢的原因:

                开启慢查询日志,不建议直接打开慢查询日志进行分析,这样比较浪费时间和精力,可以使用pt-query-digest工具进行分析。

                使用show profile,mysql命令行set profiling=1开启,于是所有执行的语句都会检测消耗时间,存到临时表中。

                通过show profile for query 临时表id 来获取查询语句在什么动作上话费多少时间。

                    image.png

                show status会返回一些计数器,show global status查看服务器级别的所有计数。有时根据这些计数,可以猜测出哪些操作代价较高或者消耗时间多。

                show processlist用来观察是否有大量线程出于不正常的状态或者特征。

                    image.png

                使用explain(用desc也一样)分析单条sql语句。

                    image.png

        优化查询过程中的数据访问:

                不要访问数据太多,只查寻需要的列和行,确认mysql服务器是否在分析大量不必要的数据行

                使用limit,指定要返回的字段,少用select *

                重复查询相同的数据,可以缓存数据,下次直接读取缓存

                是否在扫描额外的记录,使用explain进行分析,若发现查询需要扫描大量数据但只返回少量的行,可通过如下技巧优化:

                        使用索引覆盖扫描,把所有用的列都放到索引中,这样存储引擎不需要回表获取对应行就可以返回结果

                改变数据库和表结构,修改数据表范式。如适当冗余

                重写sql语句,让优化器以更优的方式执行查询(索引优化,避免索引失效的情况)

        优化长难的查询语句:

                mysql内部每秒能扫描内存中上百万行数据,相比之下,响应数据给客户端就要慢得多。使用尽可能少的查询是好的,但有时将一个大查询分解为多个小查询是很有必要的

                切分查询:比如一次删除/插入1k条,暂停一会再继续...

                分解关联查询:可以将一条关联语句分解成多条sql来执行(好处:让缓存效率更高,执行单个查询可以减少锁的竞争,在应用层做关联可以更容易对数据库进行拆分)

        优化特定类型的查询语句:

                优化count()查询,count(*)中的*会忽略所有的列,直接统计所有的列数,因此不要使用count(列名)

                myisam中,没有任何where条件的count(*)非常快,当有where条件,myisam的count统计不一定比其他表引擎快

                        可以使用explain查询近似值,用近似值替代count(*)

                        增加汇总表(用一个表记录各增删改查后表中的数据条数)

                        缓存汇总信息

                优化关联查询

                        确定on或using子句的列上有查询

                        确保group by和order by中只有一个表中的列,这样mysql才有可能使用索引

                优化子查询

                        尽量用关联查询来替代

                优化group by和distinct

                        均可用索引来优化,是最有效的优化方法

                        关联查询中,使用标识列(主键列、auto increment列)进行分组的效率会更高

                        如果不需要order by,进行group by时使用order by null,mysql不会再进行文件排序,否则可能会文件排序导致性能消耗

                        with rollup超级聚合,可以挪到应用程序处理

                优化limit分页

                        limit偏移量大,查询效率就会低

                        可以记录上次查询的最大id,下次查询时直接根据id来查询

                优化union查询

                        union all的效率高于union,可以在应用层将重复的筛选掉

                        

分库分表:

        水平分割:

                表很大,分割后可以降低在查询时需要读的数据和索引的页数,同时也降低了索引的层数,提高查询速度

                        image.png

                使用场景:

                        表中的数据本身就有独立性,例如表中分别记录各个地区的数据或不同时期的数据,特别是有些数据常用,有些不常用

                        需要把数据存放到多个介质上

                缺点:

                        给应用增加复杂度,通常查询时需要多个表名,查询所有数据都需union操作

                        在许多数据库应用中,这种复杂性会超过它带来的优点,查询时会增加读一个索引层的磁盘次数

        垂直分割:

                把主键和一些列放在一个表,然后把主键和另外的列放在另一个表中

                        image.png

                使用场景:

                        如果一个表中某些列常用,而另外一些列不常用

                        可以使数据行变小,一个数据页能存储更多数据,查询时减少io次数

                缺点:

                        管理冗余列,查询所有数据需要join操作

分库分表(水平和垂直)的缺点:

        有些表的策略基于应用层的逻辑算法,一旦逻辑算法改变,整个分表逻辑都会改变,扩展性差

        对应用层来说,逻辑算法无疑增加开发成本




主从复制原理:

        在主库上把数据更改记录到二进制日志

        从库将主库的日志复制到自己的中继日志

        从库读取中继日志中的事件,将其重放到从库数据库中

主从复制解决的问题:

        数据分布:随意停止或开始复制,并在不同地理位置分部数据备份

        负载均衡:降低单个服务器的压力

        高可用和故障切换:帮助应用程序避免单点失败

        升级测试:可以使用更高版本的mysql作为从库





sql语句安全:

        预处理,防止sql注入(通常用pdo方式)

        写入数据对特殊字符转义

        查询错误信息不要返回给客户,将错误记录到日志


        定期做数据备份

        不给查询用户root权限,合理分配权限

        关闭远程访问数据权限

        修改root口令,不用默认口令,使用较复杂口令

        删除多余用户

        改变root用户名称

        限制一般用户浏览其他库

        限制用户对数据文件的访问权限