MySQL

什么是MySQL?

MySQL 是⼀种关系型数据库,在Java企业级开发中⾮常常⽤,因为 MySQL 是开源免费的,并且⽅便扩展。阿⾥巴巴数据库系统也⼤量⽤到了 MySQL,因此它的稳定性是有保障的。MySQL是开放源代码的, 因此任何⼈都可以在 GPL(General Public License) 的许可下下载并根据个性化的需要对其进⾏修改。MySQL的默认端⼝号是3306。

数据库的三范式是什么

第一范式:列不可再分

第二范式:行可以唯一区分,主键约束

第三范式:表的非主属性不能依赖与其他表的非主属性 外键约束

且三大范式是一级一级依赖的,第二范式建立在第一范式上,第三范式建立第一第二范式上。

数据库引擎有哪些

如何查看mysql提供的所有存储引擎

mysql> show engines;

image-20210504151943563

查看MySQL当前默认的存储引擎

我们也可以通过下⾯的命令查看默认的存储引擎。

mysql> show variables like '%storage_engine%';

查看表的存储引擎

show table status like "table_name" ;

image-20210504230430379

mysql常用引擎包括:MYISAM、Innodb、Memory、MERGE

imgMYISAM:全表锁,拥有较高的执行速度,不支持事务,不支持外键,并发性能差,占用空间相对 较小,对事务完整性没有要求,以select、insert为主的应用基本上可以使用这引擎

imgInnodb:行级锁,提供了具有提交、回滚和崩溃回复能力的事务安全,支持自动增长列,支持外键 约束,并发能力强,占用空间是MYISAM的2.5倍,处理效率相对会差一些

imgMemory:全表锁,存储在内容中,速度快,但会占用和数据量成正比的内存空间且数据在mysql重 启时会丢失,默认使用HASH索引,检索效率非常高,但不适用于精确查找,主要用于那些内容变 化不频繁的代码表

imgMERGE:是一组MYISAM表的组合

InnoDB与MyISAM的区别

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实现并不统⼀。

  1. InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交, 这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

  2. InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;

  3. InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但 是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大, 因为主键太大,其他索引也都会很大。而MyISAM是非聚集索引,数据文件是分离的,索引保存的 是数据文件的指针。主键索引和辅助索引是独立的。

  4. InnoDB不保存表的具体行数,执行select count() from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;

  5. Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;

如何选择引擎?

如果没有特别的需求,使用默认的Innodb 即可。

MyISAM:以读写插入为主的应用程序,比如博客系统、新闻门户网站。

Innodb:更新(删除)操作频率也高,或者要保证数据的完整性;并发量高,支持事务和外键。比如OA自动化办公系统。

⼀般情况下我们选择 InnoDB 都是没有问题的,但是某些情况下你并不在乎可扩展能⼒和并发能⼒,也不需要事务⽀持,也不在乎崩溃后的安全恢复问题的话,选择MyISAM也是⼀个不错的选择。但是⼀般情 况下,我们都是需要考虑到这些问题的。

字符集及校对规则

字符集指的是⼀种从⼆进制编码到某类字符符号的映射。校对规则则是指某种字符集下的排序规则。

MySQL中每⼀种字符集都会对应⼀系列的校对规则。

MySQL采⽤的是类似继承的⽅式指定字符集的默认值,每个数据库以及每张数据表都有⾃⼰的默认值, 他们逐层继承。⽐如:某个库中所有表的默认字符集将是该数据库所指定的字符集(这些表在没有指定 字符集的情况下,才会采⽤默认字符集)

索引

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所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,再⾛⼀遍主索引。 因此,在设计表的时候,不建议使⽤过⻓的字段作为主键,也不建议使⽤⾮单调的字段作为主键,这样会造成主索引 频繁分裂。

索引问题

索引是对数据库表中一个或多个列的值进行排序的结构,建立索引有助于快速获取信息。

你也可以这样理解:索引就是加快检索表中数据的方法。数据库的索引类似于书籍的索引。在书籍中, 索引允许用户不必翻阅完整个书就能迅速地找到所需要的信息。在数据库中,索引也允许数据库程序迅 速地找到表中的数据,而不必扫描整个数据库。

  • 主键索引(PRIMARY)

数据列不允许重复,不允许为NULL,一个表只能有一个主键。

  • 唯一索引(UNIQUE)

数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。

可以通过ALTER TABLE table_name ADD UNIQUE (column);创建唯一索引

可以通过ALTER TABLE table_name ADD UNIQUE (column1,column2);创建唯一组合索引

  • 普通索引(INDEX)

可以通过ALTER TABLE table_name ADD INDEX(column);创建普通索引

可以通过ALTER TABLE table_name ADD INDEX(column1,column2);创建组合索引

  • 创建组合索引

可以通过ALTER TABLE table_name ADD FULLTEXT (column); 创建全文索引

索引并非是越多越好,创建索引也需要耗费资源,一是增加了数据库的存储空间,二是在插入和删除时 要花费较多的时间维护索引

  • 索引加快数据库的检索速度
  • 索引降低了插入、删除、修改等维护任务的速度
  • 唯一索引可以确保每一行数据的唯一性
  • 通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能
  • 索引需要占物理和数据空间

查询缓存的使⽤

执⾏查询语句的时候,会先查询缓存。不过,MySQL 8.0 版本后移除,因为这个功能不太实⽤

my.cnf加⼊以下配置,重启MySQL开启查询缓存

query_cache_type=1 

query_cache_size=600000

MySQL执⾏以下命令也可以开启查询缓存

set  global    query_cache_type=1;
set  global    query_cache_size=600000;

如上,开启查询缓存后在同样的查询条件以及数据情况下,会直接在缓存中返回结果。这⾥的查询条件 包括查询本身、当前要查询的数据库、客户端协议版本号等⼀些可能影响结果的信息。因此任何两个查 询在任何字符上的不同都会导致缓存不命中。此外,如果查询中包含任何⽤户⾃定义函数、存储函数、⽤户变量、临时表、MySQL库中的系统表,其查询结果也不会被缓存。

缓存建⽴之后,MySQL的查询缓存系统会跟踪查询中涉及的每张表,如果这些表(数据或结构)发⽣变 化,那么和这张表相关的所有缓存数据都将失效。

缓存虽然能够提升数据库的查询性能,但是缓存同时也带来了额外的开销,每次查询后都要做⼀次缓存 操作,失效后还要销毁。 因此,开启缓存查询要谨慎,尤其对于写密集的应⽤来说更是如此。如果开启,要注意合理控制缓存空间⼤⼩,⼀般来说其⼤⼩设置为⼏⼗MB⽐较合适。此外,还可以通过sql_cache和sql_no_cache来控制某个查询语句是否需要缓存:

select sql_no_cache count() from usr;

SQL优化

1、查询语句中不要使用select

2、尽量减少子查询,使用关联查询(left join,right join,inner join)替代3、减少使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代

4、or 的查询尽量用 union或者union all 代替(在确认没有重复数据或者不用剔除重复数据时,union all会更好)

5、应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。

6、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null 值,然后这样查询: select id from t where num=0

简单说一说drop、delete与truncate的区别

SQL中的drop、delete、truncate都表示删除,但是三者有一些差别delete和truncate只删除表的数据不删除表的结构

速度,一般来说: drop> truncate >delete

delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;

如果有相应的trigger,执行的时候将被触发. truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger.

什么是视图

视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一 个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表 查询。

什么是内联接、左外联接、右外联接?

  • 内联接(Inner Join):匹配2张表中相关联的记录。
  • 左外联接(Left Outer Join):除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记录, 右表中未匹配到的字段用NULL表示。
  • 右外联接(Right Outer Join):除了匹配2张表中相关联的记录外,还会匹配右表中剩余的记录, 左表中未匹配到的字段用NULL表示。在判定左表和右表时,要根据表名出现在Outer Join的左右位置关系。

数据库的事务

什么是事务?: 多条sql语句,要么全部成功,要么全部失败。

事务最经典也经常被拿出来说例⼦就是转账了。假如⼩明要给⼩红转账1000元,这个转账会涉及到两个 关键操作就是:将⼩明的余额减少1000元,将⼩红的余额增加1000元。万⼀在这两个操作之间突然出现 错误⽐如银⾏系统崩溃,导致⼩明余额减少⽽⼩红的余额没有增加,这样就不对了。事务就是保证这两 个关键操作要么都成功,要么都要失败。

事务的特性:

数据库事务特性:原子性(Atomic)、一致性(Consistency)、隔离性(Isolation)、持久性(Durabiliy)。 简称ACID。

  • 原子性:组成一个事务的多个数据库操作是一个不可分割的原子单元,只有所有操作都成功,整个 事务才会提交。任何一个操作失败,已经执行的任何操作都必须撤销,让数据库返回初始状态。
  • 一致性:事务操作成功后,数据库所处的状态和它的业务规则是一致的。即数据不会被破坏。如A 转账100元给B,不管操作是否成功,A和B的账户总额是不变的。
  • 隔离性:在并发数据操作时,不同的事务拥有各自的数据空间,它们的操作不会对彼此产生干扰
  • 持久性:一旦事务提交成功,事务中的所有操作都必须持久化到数据库中。

并发事务带来哪些问题?

在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对同一 数据进行操作)。并发虽然是必须的,但可能会导致以下的问题。

  • 脏读(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)就会发现多了 一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。

不可重复读和幻读区别:

不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者 删除比如多次读取一条记录发现记录增多或减少了。

事务隔离级别有哪些?MySQL的默认隔离级别是?

SQL 标准定义了四个隔离级别:

  • READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
  • READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
  • REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
  • SERIALIZABLE(可串行化):最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻 读。
隔离级别 脏读 不可重复读 幻影读
READ-UNCOMMITTED
READ-COMMITTED ×
REPEATABLE-READ × ×
SERIALIZABLE × × ×

MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。我们可以通过

imgSELECT @@tx_isolation; 命令来查看

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 存储引擎默认使用 REPEAaTABLE- READ(可重读) 并不会有任何性能损失。

InnoDB 存储引擎在 分布式事务 的情况下一般会用到 SERIALIZABLE(可串行化) 隔离级别。

锁机制与InnoDB锁算法

MyISAM和InnoDB存储引擎使⽤的锁:
  • MyISAM采⽤表级锁(table-level locking)。
  • InnoDB⽀持⾏级锁(row-level locking)和表级锁,默认为⾏级锁
表级锁和⾏级锁对⽐:
  • 表级锁: MySQL中锁定 粒度最⼤ 的⼀种锁,对当前操作的整张表加锁,实现简单,资源消耗也⽐较少,加锁快,不会出现死锁。其锁定粒度最⼤,触发锁冲突的概率最⾼,并发度最低,MyISAM和 InnoDB引擎都⽀持表级锁。
  • ⾏级锁: MySQL中锁定 粒度最⼩ 的⼀种锁,只针对当前操作的⾏进⾏加锁。 ⾏级锁能⼤⼤减少数据库操作的冲突。其加锁粒度最⼩,并发度⾼,但加锁的开销也最⼤,加锁慢,会出现死 锁。

InnoDB存储引擎的锁的算法有三种:

  • Record lock:单个⾏记录上的锁

  • Gap lock:间隙锁,锁定⼀个范围,不包括记录本身

  • Next-key lock:record+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. 垂直分区

根据数据库里面数据表的相关性进行拆分。 例如,用户表中既有用户的登录信息又有用户的基本信息, 可以将用户表拆分成两个单独的表,甚至放到单独的库做分库。

简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。 如下图所示,这样来说大家应该就更容易理解了。

image-20210504152412819

  • 垂直拆分的优点: 可以使得列数据变小,在查询时减少读取的Block数,减少I/O次数。此外,垂直分区可以简化表的结构,易于维护。
  • 垂直拆分的缺点: 主键会出现冗余,需要管理冗余列,并会引起Join操作,可以通过在应用层进行Join来解决。此外,垂直分区会让事务变得更加复杂;

4. 水平分区

保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了 分布式的目的。 水平拆分可以支撑非常大的数据量。

水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成 多张表来存放。举个例子:我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据 量过大对性能造成影响。

image-20210504152448347

水平拆分可以支持非常大的数据量。需要注意的一点是:分表仅仅是解决了单一表数据过大的问题,但 由于表的数据还是在同一台机器上,其实对于提升MySQL并发能力没有什么意义,所以 水平拆分最好分库 。 水平拆分能够 支持非常大的数据量存储,应用端改造也少,但 分片事务难以解决 ,跨节点Join性能较差,逻辑复杂。《Java工程师修炼之道》的作者推荐 尽量不要对数据进行分片,因为拆分会带来逻辑、部署、运维的各种复杂度 ,一般的数据表在优化得当的情况下支撑千万以下的数据量是没有太大问题的。如果实在要分片,尽量选择客户端分片架构,这样可以减少一次和中间件的网络I/O。 下面补充一下数据库分片的两种常见方案:

  • 客户端代理: 分片逻辑在应用端,封装在jar包中,通过修改或者封装JDBC层来实现。 当当网的Sharding-JDBC 、阿里的TDDL是两种比较常用的实现。
  • 中间件代理: 在应用和数据中间加了一个代理层。分片逻辑统一维护在中间件服务中。 我们现在谈的 Mycat 、360的Atlas、网易的DDB等等都是这种架构的实现。

解释⼀下什么是池化设计思想。什么是数据库连接池?为什么需要数据库连接池?

池化设计应该不是⼀个新名词。我们常⻅的如java线程池、jdbc连接池、redis连接池等就是这类设计 的代表实现。这种设计会初始预设资源,解决的问题就是抵消每次获取资源的消耗,如创建线程的开销,获取远程连接的开销等。就好⽐你去⻝堂打饭,打饭的⼤妈会先把饭盛好⼏份放那⾥,你来了就直 接拿着饭盒加菜即可,不⽤再临时⼜盛饭⼜打菜,效率就⾼了。除了初始化资源,池化设计还包括如下 这些特征:池⼦的初始值、池⼦的活跃值、池⼦的最⼤值等,这些特征可以直接映射到java线程池和数据库连接池的成员属性中。这篇⽂章对池化设计思想介绍的还不错,直接复制过来,避免重复造轮⼦了。

数据库连接本质就是⼀个 socket 的连接。数据库服务端还要维护⼀些缓存和⽤户权限信息之类的 所以占⽤了⼀些内存。我们可以把数据库连接池是看做是维护的数据库连接的缓存,以便将来需要对数据 库的请求时可以重⽤这些连接。为每个⽤户打开和维护数据库连接,尤其是对动态数据库驱动的⽹站应⽤程序的请求,既昂贵⼜浪费资源。在连接池中,创建连接后,将其放置在池中,并再次使⽤它,因此 不必建⽴新的连接。如果使⽤了所有连接,则会建⽴⼀个新连接并将其添加到池中。 连接池还减少了⽤户必须等待建⽴与数据库的连接的时间。

分库分表之后,id 主键如何处理?

因为要是分成多个表之后,每个表都是从 1 开始累加,这样是不对的,我们需要一个全局唯一的 id 来支持。

生成全局 id 有下面这几种方式:

  • UUID:不适合作为主键,因为太长了,并且无序不可读,查询效率低。比较适合用于生成唯一的 名字的标示比如文件的名字。
  • 数据库自增 id : 两台数据库分别设置不同步长,生成不重复ID的策略来实现高可用。这种方式生成的 id 有序,但是需要独立部署数据库实例,成本高,还会有性能瓶颈。
  • 利用 redis 生成 id : 性能比较好,灵活方便,不依赖于数据库。但是,引入了新的组件造成系统更加复杂,可用性降低,编码更加复杂,增加了系统成本。

img

mysql有关权限的表都有哪几个

MySQL服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。下面分别介绍一下这些表的结构和内容:

  • user权限表:记录允许连接到服务器的用户帐号信息,里面的权限是全局级的。db权限表:记录各个帐号在各个数据库上的操作权限。
  • table_priv权限表:记录数据表级的操作权限。columns_priv权限表:记录数据列级的操作权限。
  • host权限表:配合db权限表对给定主机上数据库级操作权限作更细致的控制。这个权限表不受GRANT和REVOKE语句的影响。

mysql有哪些数据类型

1、整数类型 ,包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分别表示1字节、2字节、3 字节、4字节、8字节整数。任何整数类型都可以加上UNSIGNED属性,表示数据是无符号的,即非负整 数。

长度:整数类型可以被指定长度,例如:INT(11)表示长度为11的INT类型。长度在大多数场景是没有意 义的,它不会限制值的合法范围,只会影响显示字符的个数,而且需要和UNSIGNED ZEROFILL属性配合使用才有意义。

例子,假定类型设定为INT(5),属性为UNSIGNED ZEROFILL,如果用户插入的数据为12的话,那么数据库实际存储数据为00012。

2、实数类型,包括FLOAT、DOUBLE、DECIMAL。

DECIMAL可以用于存储比BIGINT还大的整型,能存储精确的小数。而FLOAT和DOUBLE是有取值范围的,并支持使用标准的浮点进行近似计算。计算时FLOAT和DOUBLE相比DECIMAL效率更高一些,DECIMAL你可以理解成是用字符串进行处理。

3、字符串类型,包括VARCHAR、CHAR、TEXT、BLOB VARCHAR用于存储可变长字符串,它比定长类型更节省空间。

VARCHAR使用额外1或2个字节存储字符串长度。列长度小于255字节时,使用1字节表示,否则使用2字节表示。

VARCHAR存储的内容超出设置的长度时,内容会被截断。CHAR是定长的,根据定义的字符串长度分配足够的空间。CHAR会根据需要使用空格进行填充方便比较。

CHAR适合存储很短的字符串,或者所有值都接近同一个长度。CHAR存储的内容超出设置的长度时,内容同样会被截断。

使用策略:

对于经常变更的数据来说,CHAR比VARCHAR更好,因为CHAR不容易产生碎片。对于非常短的列,CHAR比VARCHAR在存储空间上更有效率。

使用时要注意只分配需要的空间,更长的列排序时会消耗更多内存。

尽量避免使用TEXT/BLOB类型,查询时会使用临时表,导致严重的性能开销。

4、枚举类型(ENUM),把不重复的数据存储为一个预定义的集合。有时可以使用ENUM代替常用的字符串类型。

ENUM存储非常紧凑,会把列表值压缩到一个或两个字节。ENUM在内部存储时,其实存的是整数。

尽量避免使用数字作为ENUM枚举的常量,因为容易混乱。排序是按照内部存储的整数

5、日期和时间类型,尽量使用timestamp,空间效率高于datetime, 用整数保存时间戳通常不方便处理。

如果需要存储微妙,可以使用bigint存储。

看到这里,这道真题是不是就比较容易回答了。

创建索引的三种方式,删除索引

第一种方式:在执行CREATE TABLE时创建索引

CREATE TABLE user_index2 (
id INT auto_increment PRIMARY KEY, first_name VARCHAR (16),
last_name VARCHAR (16),
id_card VARCHAR (18), information text,
KEY name (first_name, last_name), FULLTEXT KEY (information), UNIQUE KEY (id_card)
);

第二种方式:使用ALTER TABLE命令去增加索引

ALTER TABLE table_name ADD INDEX index_name (column_list);

ALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引。

其中table_name是要增加索引的表名,column_list指出对哪些列进行索引,多列时各列之间用逗号分 隔。

索引名index_name可自己命名,缺省时,MySQL将根据第一个索引列赋一个名称。另外,ALTER TABLE允许在单个语句中更改多个表,因此可以在同时创建多个索引。

第三种方式:使用CREATE INDEX命令创建

CREATE INDEX index_name ON table_name (column_list);

CREATE INDEX可对表增加普通索引或UNIQUE索引。(但是,不能创建PRIMARY KEY索引) 删除索引

根据索引名删除普通索引、唯一索引、全文索引: alter table 表名 drop KEY 索引名

alter table user_index drop KEY name; 
alter table user_index drop KEY id_card;
alter table user_index drop KEY information;

删除主键索引: alter table 表名 drop primary key (因为主键只有一个)。这里值得注意的是, 如果主键自增长,那么不能直接执行此操作(自增长依赖于主键索引)

image-20210504152804526

需要取消自增长再行删除:

alter table user_index
-- 重新定义字段
MODIFY id int, drop PRIMARY KEY

但通常不会删除主键,因为设计主键一定与业务逻辑无关。

⼀条SQL语句在MySQL中如何执⾏的

img

MySQL⾼性能优化规范建议

⼀条SQL语句执⾏得很慢的原因有哪些?

书写⾼质量SQL的30条建议

results matching ""

    No results matching ""