MySQL高级学习笔记
Posted 二木成林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL高级学习笔记相关的知识,希望对你有一定的参考价值。
文章目录
第1章 mysql的架构介绍
1.1 MySQL简介
官网:https://www.mysql.com/
MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司
MySQL 是一种关联数据库管理系统(RDBMS), 将数据保存在不同的表中,而不是将所有数据放在一个大的仓库内,这样就增加了速度并提高了灵活性。
MySQL 特征
- MySQL 是开源的,所以你不需要支付额外的费用。
- MySQL 支持大型的数据库。可以处理拥有处理上千万条记录的大型数据库。
- MySQL 可以允许于多个系统上,并且支持多种语言,这些编程语言包含 C、C++、Java、Perl、php 、 Eiffel 、 Ruby 和 Tcl 等。
- MySQL对 PHP 有很好的支持, PHP 是暮年最流行的 WEB 开发语言之一。
- MySQL 支持大型数据库, 支持 5000W 条数据记录的数据仓库, 32 为操作系统最大可支持 4GB , 64位操作系统最大的表文件为 8TB。
- MySQL 是可以支持定制的,采用了 GPL协议, 你可以修改源码来开发自己的MySQL 系统。
1.2 在Linux上安装MySQL
MySQL高级的应用都是在Linux系统上进行,是对数据库的优化。
请参考博客:在Linux中安装MySQL
1.3 MySQL配置文件
Windows系统下mysql的配置文件为my.ini文件,Linux系统下mysql的配置文件为/etc/my.cnf文件。
MySQL主要配置文件如下:
- 二进制日志log-bin:用于主从复制
- 错误日志log-error:默认是关闭的,记录严重的警告和错误信息,每次启动和关闭的详细信息等
- 查询日志log:默认关闭,记录查询的sql语句,如果开启会减低mysql的整体性能,因为记录日志也是需要消耗系统资源的
- 数据文件
- 两系统
- mysql安装目录下的data目录下可以挑选很多库
- 默认路径:/var/lib/mysql
- frm文件:存放表结构
- myd文件:存放表数据
- myi文件:存放表索引
- 两系统
1.3 MySQL逻辑架构介绍
总体架构:
总体架构说明:
1、连接层:提供客户端和连接服务,包含本地Sock通信和大多数基于客户端/服务端工具实现的类似于TCP/IP的通信,主要完成一些类似于连接处理、授权认证、及相关的安全方案,在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程,同样在该层上可以实现基于SSL的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。注:分配数据库连接线程池,控制数据库的连接和关闭等资源。
2、业务逻辑处理层:主要完成大多数的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化及部分内置函数的操作。所有跨操作引擎的功能也在这一层实现,如过程,函数等。在该层服务器会解析查询并创建相应的内部解析树,并对其完成相应的优A化如确定查询表的顺序,是否利用索引等,最后生成相应的执行操作。如果是SELECT语句,服务器还会查询内部的缓存,如果缓存空间足够大,这样在解决大量读操作的环境中能够很好的提升系统的性能。注:提供SQL操作的接口,对SQL脚本按一定规则进行解析,并通过SQL优化器优化执行顺序,对于查询的语句还会进入缓存区,提升系统的性能。
3、数据存储引擎层:存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过API与存储引[擎进行通信,不同的存储引|擎具有的功能不同,这样我们可以根据自己的实际需要进行选选取。注:存储引擎都是可插拔的,每个存储引l擎所提供的服务都有所差异,所以我们需要根据具体的业务需要,选择合适的存储引[擎,常用的只有两种MyISAM和lnnoDB。
4、数据存储层:主要是将数据存储在运行于裸设备的文件系统上,并完成与存储引擎的交互。注:将数据存储到磁盘上,并协同存储引擎对数据进行读写操作。
数据库逻辑结构共分为四层,分别是连接层(线程连接池)、业务逻辑处理层(SQL解析读取)、数据存储引擎层(存储擎)、数据存储层〈(数据存储)和其它的数据库相比,MySQL有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用,主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提取相分离,这种架构可以根据业务的需求和实际需要选择合适的存储引擎。
1.4 MySQL存储引擎
1.4.1 查看命令
可以通过如下命令查看支持的存储引擎:
show engines; #查看支持的存储引擎
通过如下命令查看当前默认的存储引擎:
show variables like '%storage_engines%'; #查看当前默认的存储引擎
1.4.2 MyISAM和InnoDB
第2章 索引优化分析
2.1 概述
2.1.1 性能下降原因
性能下降SQL慢,执行时间长,等待时间长的原因:
- 查询语句写的烂
- 索引失效:单值和复合
- 关联查询太多join(设计缺陷或不得已的需求)
- 服务器调优及各个参数设置不合理(缓冲、线程数等)
2.1.2 常用的join查询
2.1.2.1 SQL执行顺序
①手写
通常我们按照需求写的SQL查询语句是这样的:
SELECT DISTINCT查询列表
FROM 左表 INNER|LEFT|RIGHT
JOIN 右表 ON 连接条件
WHERE 分组前的筛选条件
GROUP BY 分组列表
HAVING 分组后的筛选条件
ORDER BY 排序列表
LIMIT 分页参数
我们手写的SQL中SELECT在最前面的位置。
②机读
随着 Mysql 版本的更新换代,其优化器也在不断的升级,优化器会分析不同执行顺序产生的性能消耗不同而动态调整执行顺序。下面是经常出现的查询顺序:
FROM 左表 INNER|LEFT|RIGHT
JOIN 右表 ON 连接条件
WHERE 分组前的筛选条件
GROUP BY 分组列表
HAVING 分组后的筛选条件
SELECT DISTINCT查询列表
ORDER BY 排序列表
LIMIT 分页参数
而在机读中FROM是最先执行的。
③总结
2.1.2.2 join图
- 左外连接
A表独有部分+AB两表的公有部分。
-- SQL语句如下:
SELECT 查询列表 FROM A LEFT JOIN B ON A.key=B.key# 其中A.key=B.key指的是连接条件
-- 注:
-- 左外连接中左边的是主表,右边的是从表
- 右外连接
-- SQL语句如下:
SELECT 查询列表 FROM A RIGHT JOIN B ON A.key=B.key# 其中A.key=B.key指的是连接条件
-- 注:
-- 右外连接中右边的是主表,左边的是从表
- 内连接
获取的是两张表的公有部分。
-- SQL语句如下:
SELECT 查询列表 FROM A INNER JOIN B ON A.key=B.key# 其中A.key=B.key指的是连接条件
-- 注:
-- 内连接求的是多张表的交集部分
- 左外连接去除交集
SELECT 查询列表 FROM A LEFT JOIN B ON A.key=B.key WHERE B.key IS NULL;# 将从表B的连接条件作为NULL值判断
- 右外连接去除交集
SELECT 查询列表 FROM A RIGHT JOIN B ON A.key=B.key WHERE A.key IS NULL;# 将从表A的连接条件作为NULL值判断
- 全外连接
注意:MySQL不支持full join。
SELECT 查询列表 FROM A FULL JOIN B ON A.key=B.key;# 全外连接就是求并集
# 可以间接完成效果
SELECT 查询列表 FROM A LEFT JOIN B ON A.key=B.key
UNION
SELECT 查询列表 FROM A RIGHT JOIN B ON A.key=B.key
- 全外连接去除交集
SELECT 查询列表 FROM A FULL JOIN B ON A.key=B.key WHERE A.key IS NULL OR B.key IS NULL;
实例如下:
-- 左外连接
select * from beauty left join boys on beauty.boyfriend_id=boys.id;
-- 右外连接
select * from beauty right join boys on beauty.boyfriend_id=boys.id;
-- 内连接
select * from beauty inner join boys on beauty.boyfriend_id=boys.id;
-- 左外连接去除交集
select * from beauty left join boys on beauty.boyfriend_id=boys.id where boys.id IS NULL;
-- 右外连接去除交集
select * from beauty right join boys on beauty.boyfriend_id=boys.id where beauty.boyfriend_id IS NULL;
-- 全外连接(MySQL不能运行)
select * from beauty full join boys on beauty.boyfriend_id=boys.id;
-- 全外连接去除交集(MySQL不能运行)
select * from beauty full join boys on beauty.boyfriend_id=boys.id where boys.id IS NULL OR beauty.boyfriend_id IS NULL;
2.2 索引简介
2.2.1 索引是什么
MySQL 官方对索引的定义为:索引(Index)是帮助 MySQL 高效获取数据的数据结构。可以得到索引的本质:索引是数据结构。可以简单理解为排好序的快速查找数据结构。
在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。下图就是一种可能的索引方式示例:
左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址 。 为了加快 Col2 的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指 针,这样就可以运用二叉查找在一定的复杂度内获取到相应数据,从而快速的检索出符合条件的记录。
我们平常所说的索引,如果没有特别指明,都是指B树(多路搜索树,并不一定是二叉的)结构组织的索引。其中聚集索引,次要索引,覆盖索引,复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引。当然,除了B+树这种类型的索引之外,还有哈希索引(hashindex)等。
一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。
2.2.2 索引的优缺点
优势:
- 类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本
- 通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗
劣势:
- 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的。
- 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。
- 索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句
2.2.3 索引的分类
索引可以分为单值索引、唯一索引、主键索引和复合索引。
2.2.3.1 单值索引
即一个索引只包含单个列,一个表可以有多个单列索引。
创建单值索引的语法如下:
-- 创建情况一:在创建表时创建
CREATE TABLE 表名(
字段名 字段类型 [约束],
字段名 字段类型 [约束],
...
字段名 字段类型 [约束],
KEY(字段名)# 这一句就是创建单列索引的语句,直接在KEY()中写字段名即可
);
-- 创建情况二:单独创建单值索引
CREATE INDEX 索引名 ON 表名(字段名);
# 注释:
# 1.索引名通常是idx_表名_字段名这样的格式,比如idx_user_name
# 2.单独创建索引的示例:CREATE INDEX idx_user_name user(nmae);
2.2.3.2 唯一索引
即索引列的值必须唯一,但允许有空值。
创建唯一索引的语法如下:
-- 创建情况一:在创建表时创建
CREATE TABLE 表名(
字段名 字段类型 [约束],
字段名 字段类型 [约束],
...
字段名 字段类型 [约束],
UNIQUE(字段名)# 这一句就是创建唯一索引的语句,直接在UNIQUE()中写字段名即可
);
-- 创建情况二:单独创建唯一索引
CREATE UNIQUE INDEX 索引名 ON 表名(字段名);
# 注释:
# 1.索引名通常是idx_表名_字段名这样的格式,比如idx_user_name
# 2.单独创建唯一索引的示例:CREATE UNIQUE INDEX idx_user_id user(id);
2.2.3.3 主键索引
设定某字段为主键后,数据库会自动建立索引,innodb存储引擎的主键为聚簇索引。
创建索引的基本语法如下:
-- 创建情况一:在创建表时创建
CREATE TABLE 表名(
字段名 字段类型 [约束],
字段名 字段类型 [约束],
...
字段名 字段类型 [约束],
PRIMARY KEY(字段名)# 这一句就是创建主键索引的语句,直接在PRIMARY KEY()中写字段名即可
);
-- 创建情况二:单独创建主键索引
ALTER TABLE 表名 ADD PRIMARY KEY 表名(字段名);
# 注释:
# 1.创建示例:ALTER TABLE user ADD PRIMARY KEY user(id);
-- 删除主键索引
ALTER TABLE 表名 DROP PRIMARY KEY;
# 注释:
# 1.删除示例:ALTER TABLE user DROP PRIMARY KEY;
# 2.如果要修改主键索引,那么必须先删除掉原索引,再新建索引
2.2.3.4 复合索引
即一个索引包含多个列。
创建的基本语法如下:
-- 创建情况一:在创建表时创建
CREATE TABLE 表名(
字段名 字段类型 [约束],
字段名 字段类型 [约束],
...
字段名 字段类型 [约束],
KEY(字段名,字段名,..)# 这一句就是创建复合索引的语句,直接在KEY()中写多个字段名即可
);
-- 创建情况二:单独创建复合索引
CREATE INDEX 索引名 ON 表名(字段名,字段名,...);
2.2.4 基本语法
①创建索引
-- 语法
CREATE [UNIQUE] INDEX 索引名 ON 表名(字段名[,字段名,字段名,..]);
②删除索引
-- 语法
DROP INDEX 索引名 ON 表名;
③查看索引
-- 语法
SHOW INDEX FROM 表名;
④修改索引
-- 语法
-- 通过修改语句添加主键索引
ALTER TABLE 表名 ADD PRIMARY KEY(字段名);# 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为 NULL。
-- 通过修改语句添加普通索引
ALTER TABLE 表名 ADD INDEX 索引名(字段名,[字段名,..]);# 添加普通索引
-- 通过修改语句添加全文索引
ALTER TABLE 表名 ADD FULLTEXT 索引名(字段名,[字段名,..]);# 该语句指定了索引为FULLTEXT,用于全文索引
2.2.5 索引的创建时机
2.2.5.1 适合创建索引的情况
- 主键自动建立唯一索引;
- 频繁作为查询条件的字段应该创建索引
- 查询中与其它表关联的字段,外键关系建立索引
- 单键/组合索引的选择问题, 组合索引性价比更高
- 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
- 查询中统计或者分组字段
- 频繁更新的字段不适合创建索引,因为每次更新不单单是更新了记录,还会更新索引,加重了IO负担。
- where条件里用不到的字段不创建索引。
2.2.5.2 不适合创建索引的情况
- 表记录太少
- 经常增删改的表或者字段
- Where 条件里用不到的字段不创建索引(注:虽然提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件)
- 数据重复且分布平均的表字段,因此应该只为最经常查询和最经常排序的数据列建立索引。注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。(注:比如国籍,全是中国人,那么没必要创建索引;又或者性别,不是’男’就是’女’也没必要创建索引)
2.3 性能分析
2.3.1 MySQL Query Optimizer
1、Mysql中有专门负责优化SELECT语句的优化器模块,主要功能:通过计算分析系统中收集到的统计信息,为客户端请求的Query提供他认为最优的执行计划(他认为最优的数据检索方式,但不见得是DBA认为是最优的,这部分最耗费时间)
2、当客户端向MySQL请求一条Query,命令解析器模块完成请求分类,区别出是SELECT并转发给MySQLQuery Optimizer时,MySQL Query Optimizer首先会对整条Query进行优化,处理掉一些常量表达式的预算,直接换算成常量值。并对Query中的查询条件进行简化和转换,如去掉一些无用或显而易见的条件、结构调整等。然后分析Query中的Hint信息(如果有),看显示Hint信息是否可以完全确定该Query的执行计划。如果没有Hint或Hint信息还不足以完全确定执行计划,则会读取所涉及对象的统计信息,根据Query进行写相应的计算分析,然后再得出最后的执行计划。
2.3.2 MySQL常见瓶颈
- CPU:CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时候
- IO:磁盘I/O瓶颈发生在装入数据远大于内存容量的时候
- 服务器硬件的性能瓶颈: top,free, iostat和vmstat来查看系统的性能状态
2.3.3 Explain
2.3.3.1 是什么
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。
2.3.3.2 能干啥
- 表的读取顺序
- 数据读取操作的操作类型哪些索引可以使用
- 哪些索引被实际使用表之间的引用
- 每张表有多少行被优化器查询
2.3.3.3 怎么玩
-- 语法
EXPLAIN 查询语句;
-- 示例
EXPLAIN SELECT * FROM user;
查询出来所包含的信息如下:
示例:
2.3.3.4 字段解释
2.3.3.4.1 id
select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序
三种情况:
- id相同,执行顺序由上至下
- id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
- id相同不同,同时存在
说了表的读取顺序:先加载括号内的子查询。
2.3.3.4.2 select_type
select_type有如下类型值:
- SIMPLE:简单的select查询,查询中不包含子查询或者UNION。
- PRIMARY:查询中若包含任何复杂的子查询,则最外层的查询被标记为PRIMARY。
- SUBQUERY:在SELECT或WHERE列表中包含的子查询。
- DERIUED:在FROM列表中包含的子查询被标记为DERIVED(衍生),MySQL会递归执行这些子查询,把结果放在临时表中。
- UNION:若第二个SELECT出现在UNION之后,则被标记为UNION。若UNION包含在FROM子句的子查询中,则外层SELECT将被标记为DERIVED。
- UNION RESULT:从UNION表获取结果的SELECT。
查询的类型select_type主要用于区别普通查询、联合查询、子查询等复杂查询。
2.3.3.4.3 table
显示这一行的数据是关于哪张表的。
2.3.3.4.4 type
一般上百万条数据才进行优化。
type是访问类型排列,显示查询使用了何种类型,跟索引优化有很大的关系,需掌握。type的值有如下几种:
- system:表只有一行记录(等于系统表),这是const类型的特列,平时不会出现,这个也可以忽略不计。
- const:表示通过索引一次就找到了,const用于比较primary key或者unique索引。因为只匹配一行数据,所以很快如将主键置于where列表中,MySQL就能将该查询转换为一个常量。
- eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描。
- ref:非唯一性索引扫描,返回匹配某个单独值的所有行。本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体。
- range:只检索给定范围的行,使用一个索引来选择行。key 列显示使用了哪个索引一般就是在你的where语句中出现了between、<、>、in等的查询
这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束语另一点,不用扫描全部索引。 - index:全索引扫描,index与ALL的区别为index只遍历索引树而非全表。通常比ALL快,因为索引文件通常比数据文件小。也就是all和index都是读全表,但index从索引中读取,而all从硬盘中读取。
- all:全表扫描,将遍历全表找到匹配的行。
从最好到最差依次是:system>const>eq_ref>ref>range>index>all。
注:一般来说,得保证查询至少达到range级别,最好能达到ref。
如果百万级别或千万级别的记录查询出现的type是all,那么就需要考虑优化了。
2.3.3.4.5 possible_keys
显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出, 但不一定被查询实际使用。是列出理论上可能会被用到的索引。
2.3.3.4.6 key
列出实际上被用到的索引。如果为NULL,则没有使用索引。
通常同possible_keys来说,possible_keys是理论上可能会被用到的索引,而key是实际上用到的索引。例如请客估计应该来10人,这是possible_keys,而当天实际上来了6人,这是key。
若查询中使用了覆盖索引,则该索引和查询的select字段重叠。所谓的覆盖索引就是查询的字段正好是复合索引中的字段列表,那么就直接在索引中查找,而不是从全表中查找,如下图:
2.3.3.4.7 key_len
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。 key_len 字段能够帮你检查是否充分的利用上了索引。ken_len 越长,说明索引使用的越充分。但使用的长度越小越好。
如何计算:
- ①先看索引上字段的类型+长度比如 int=4 ; varchar(20) =20 ; char(20) =20
- ②如果是 varchar 或者 char 这种字符串字段,视字符集要乘不同的值,比如 utf-8 要乘 3,GBK 要乘 2,
- ③varchar 这种动态字符串要加 2 个字节
- ④允许为空的字段要加 1 个字节
第一组:key_len=age 的字节长度+name 的字节长度=4+1 + (20*3+2)=5+62=67
第二组:key_len=age 的字节长度=4+1=5
2.3.3.4.8 ref
显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值。
如"const"表示一个常量,"mytest.emp.deptno"表示"mytest"数据库的"emp"表的"deptno"列的索引被使用了。
2.3.3.4.9 rows
根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数。
rows 列显示 MySQL 认为它执行查询时必须检查的行数。越少越好!
2.3.3.4.10 extra
extra中包含不适合在其他列中显示,但又十分重要的额外信息。
它可能的值有如下几种情况(重点关于①、②、③的情况):
①Using filesort
说明mysql 会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL 中无法利用索引完成的排序操作称为“文件排序”。
注:出现了这个值就应该对查询语句进行优化了。
出现 filesort 的情况:
优化后,不再出现 filesort 的情况:
查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度(即将排序的字段添加到索引)。
②Using temporary
使了用临时表保存中间结果,MySQL 在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。
注:出现了这个值就应该对查询语句进行优化了。
优化前:
将group by、order by后面的字段添加到索引中去,如果已有索引,那么它们后面的字段的顺序应该跟复合索引中的字段顺序一样。
优化后:
③Using index
Using index 代表表示相应的 select 操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率不错!如果同时出现 using where,表明索引被用来执行索引键值的查找;如果没有同时出现 using where,表明索引只是用来读取数据而非利用索引执行查找。
利用索引进行了排序或分组。
④Using where
表明使用了 where 过滤。
⑤Using join buffer
使用了连接缓存。
⑥impossible where
where 子句的值总是 false,不能用来获取任何元组。比如查找一个人名字既为"张三"又为"李四",不可能筛选成功。
⑦ select tables optimized away
在没有 GROUPBY 子句的情况下,基于索引优化 MIN/MAX 操作或者对于 MyISAM 存储引擎优化 COUNT(*)操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化。
在 innodb 中:
在 Myisam 中:
⑧distinct
优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作。
例子练习:
2.4 索引优化
2.4.1 索引分析
2.4.1.1 单表
①创建测试表
测试用的数据如下:
CREATE TABLE IF NOT EXISTS `article`(
`id` INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
`author_id` INT (10) UNSIGNED NOT NULL,
`category_id` INT(10) UNSIGNED NOT NULL ,
`views` INT(10) UNSIGNED NOT NULL ,
`comments` INT(10) UNSIGNED NOT NULL,
`title` VARBINARY(255) NOT NULL,
`content` TEXT NOT NULL
);
INSERT INTO `article`(`author_id`,`category_id` ,`views` ,`comments` ,`title` ,`content` )VALUES
(1,1,1,1,'1&以上是关于MySQL高级学习笔记的主要内容,如果未能解决你的问题,请参考以下文章