1.MySqlSlap
MySQLSlap是从MySQL的5.1.4版开始就开始官方提供的压力测试工具 创建schema、table、test data ; 运行负载测试,可以使用多个并发客户端连接; 测试环境清理 (删除创建的数据、表等,断开连接)
MySQLSlap是从MySQL的5.1.4版开始就开始官方提供的压力测试工具
mysql性能测试
./mysqlslap -uroot -proot --concurrency=1000 --iterations 10 -a --auto-generate-sql-add-autoincrement --engine=innodb --number-of-queries
=1000
./mysqlslap -uroot -proot --concurrency=1,50,100,200 --iterations=3 --number-char-cols=5 --number-int-cols=5 --auto-generate-sql --auto-generate-sql-add-autoincrement --engine=myisam,innodb --create-schema='test1'
2.mysql逻辑架构-sql层处理
2.1逻辑架构缓存
这一层主要功能有:SQL语句的解析、优化,缓存的查询,MySQL内置函数的实现,跨存储引擎功能(所谓跨存储引擎就是说每个引擎都需提供的功能(引擎需对外提供接口)),例如:存储过程、触发器、视图等。
1.如果是查询语句(select语句),首先会查询缓存是否已有相应结果,有则返回结果,无则进行下一步(如果不是查询语句,同样调到下一步) 2.解析查询,创建一个内部数据结构(解析树),这个解析树主要用来SQL语句的语义与语法解析; 3.优化:优化SQL语句,例如重写查询,决定表的读取顺序,以及选择需要的索引等。这一阶段用户是可以查询的,查询服务器优化器是如何进行优化的,便于用户重构查询和修改相关配置,达到最优化。这一阶段还涉及到存储引擎,优化器会询问存储引擎,比如某个操作的开销信息、是否对特定索引有查询优化等。
-- 查询缓存是否开启 show variables like '%query_cache_type%'; -- 查询缓存的大小 show VARIABLES like '%query_cache_size%'; -- 设置缓存的大小 SET GLOBAL query_cache_size = 134217728;
2.2逻辑架构优化
-- 执行计划 EXPLAIN select * from dept1 where db_source = 'clouddb011';
3.存储引擎
-- 查看现已提供的引擎 show engines;
-- 查看mysql当前默认的存储引擎 show variables like '%storage_engine%';
-- 查看创建表语句 show create table dept1;
MyISAM引擎
特性: 并发性与锁级别-表级锁 支持全文检索 支持数据压缩 myisampack -b -f testmysam.MYI
适用场景: 非事务型应用(数据仓库,报表,日志数据) 只读类应用 空间类应用(空间函数,坐标)
Innodb引擎
MySql 5.5以及以后版本默认存储引擎
innodb_file_per_table
ON:独立的表空间:tablename.ibd
OFF:系统表空间:ibdataX
-- 查看表空间
show VARIABLES like 'innodb_file_per_table'
-- 设置
set global innodb_file_per_table=off
mysql5.6以前默认为系统表空间 系统表空间和独立表空间 系统表空间无法简单的收缩文件大小 独立表空间可以通过optimize table 收缩系统文件 系统表空间会产生IO瓶颈 独立表空间可以同时向多个文件刷新数据 建议:Innodb使用独立表空间
OPTIMIZE TABLE dept1 set global innodb_file_per_table=off
特性 Innodb是一种事务性存储引擎 完全支持事务得ACID特性 Redo Log 和 Undo Log Innodb支持行级锁(并发程度更高) 适用场景 Innodb适合于大多数OLTP应用
show VARIABLES like 'innodb_log_buffer_size' ; show VARIABLES like 'innodb_log_files_in_group';
MyISAM与InnoDB对比
存储引擎-CSV
特点 以csv格式进行数据存储 所有列都不能为null的 不支持索引(不适合大表,不适合在线处理) 可以对数据文件直接编辑(保存文本文件内容)
存储引擎-Archive
组成 以zlib对表数据进行压缩,磁盘I/O更少 数据存储在ARZ为后缀的文件中 特点: 只支持insert和select操作 只允许在自增ID列上加索引
使用场景 日志和数据采集应用
存储引擎-Memory
文件系统存储特点 也称HEAP存储引擎,所以数据保存在内存中 支持HASH索引和BTree索引 所有字段都是固定长度 varchar(10) = char(10) 不支持Blog和Text等大字段 Memory存储引擎使用表级锁 最大大小由max_heap_table_size参数决定
存储引擎-Ferderated
特点 提供了访问远程MySQL服务器上表的方法 本地不存储数据,数据全部放到远程服务器上 本地需要保存表结构和远程服务器的连接信息 使用场景 偶尔的统计分析及手工查询
如何使用 默认禁止,启用需要再启动时增加federated参数 mysql://user_name[:password]@hostname[:port_num]/db_name/table_name
4.MySQL中的锁
MySQL的锁机制比较简单 其最显著的特点是不同的存储引擎支持不同的锁机制 比如: MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking); InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
仅从锁的角度来说: 表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如OLAP系统 行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。 很难笼统地说哪种锁更好,只能就具体应用的特点来说哪种锁更合适
4.1MyISAM的表锁
MySQL的表级锁有两种模式: 表共享读锁(Table Read Lock) 表独占写锁(Table Write Lock)
共享读锁语法 给表加锁 加共享读锁 lock table 表名 read
-- 读锁 lock table test1 READ -- 启动一个session -- 解锁 UNLOCK TABLES; -- 可以查询 select * from test1; -- 不可以插入,修改,删除 (报错) insert into test1 VALUES('test','cloundb01'); -- 同一个session查询不同的表 (报错) select * from test2; -- 同一个session 查询有别名 (报错) select a.* from test1 as a; -- lock table 表名 as 别名 read; -- 别名读锁 lock table test1 as a READ; -- 同一个session 查询有别名 (正确) select a.* from test1 as a; -- --------------另一个session----------------------------------- -- 另一个session查询同一个表(正确) select * from test1; -- 另一个session 插入数据 (等待) insert into test1 VALUES('test','cloundb01'); -- 另一个session 不同表插入数据 (可插入) insert into test2 VALUES(99999,'test','cloundb01'); 查看 show status LIKE 'table_locks_waited' 表被锁过几次
表独占写锁语法 给表加锁 加独占写锁 lock table 表名 write
lock table test1 WRITE; -- 在同一个session中 (报错) insert into test1 VALUES('test','cloundb01'); -- 在同一个session中 查询 (可查) select * from test1; -- 在同一个session中 查询不同表 (不可查) select * from test2; -- 在同一个session中不同表插入 (不可) insert into test2 VALUES(9999,'test','cloundb01');
对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求
对MyISAM表的读操作,不会阻塞当前session对表读,但对表进行修改会报错
一个session使用LOCK TABLE命令给表f加了读锁,这个session可以查询锁定表中的记录,但更新或访问其他表都会提示错误;
另外一个session可以查询表中的记录,但更新就会出现锁等待
对 MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作;
对 MyISAM表的写操作,当前session可以对本表做CRUD,但对其他表进行操作会报错
InnoDb行锁
在mysql 的 InnoDB引擎支持行锁 行锁: 共享锁又称:读锁。当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行写操作,也不允许其他事务给这几行上排它锁,但允许上读锁。 排它锁又称:写锁。当一个事务对某几个上写锁时,不允许其他事务写,但允许读。更不允许其他事务给这几行上任何锁。包括写锁。
语法
上共享锁的写法:lock in share mode 例如: select * from 表 where 条件 lock in share mode;
上排它锁的写法:for update 例如:select * from 表 where 条件 for update;
注意: 1.两个事务不能锁同一个索引。
2.insert ,delete , update在事务中都会自动默认加上排它锁。
3.行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。
第一个session中 select * from testdemo where id =1 for update 第二个session select * from testdemo where id =1 lock in share mode 回到第一个session UNLOCK TABLES 并不会解锁 使用commit 或者 begin或者ROLLBACK 才会解锁
2.再来看下表锁 lock table testdemo WRITE 使用commit,ROLLBACK 并不会解锁 使用UNLOCK TABLES 或者begin会解锁
物理结构修改
1. 首先创建一个和你要执行的alter操作的表一样的空的表结构。 2. 执行我们赋予的表结构的修改,然后copy原表中的数据到新表里面。 3. 在原表上创建一个触发器在数据copy的过程中,将原表的更新数据的操作全部更新到新的表中来。 4. copy完成之后,用rename table 新表代替原表,默认删除原表。
触发器编写例子:
delimiter || drop TRIGGER if EXISTS test1_tr || create TRIGGER test1_tr AFTER INSERT on test1 for EACH ROW BEGIN INSERT INTO test2(deptno,dname,db_source) VALUES(new.deptno,new.dname,new.db_source); END || delimiter; -- 插入数据 INSERT INTO test1(deptno,dname,db_source) VALUES(8888,'qwe','iop'); -- 查询表2数据 select * from test2; -- 删除触发器 drop TRIGGER test1_tr; -- 查询触发器 show TRIGGERS ;
物理结构修改-pt-online-schema-change
下载安装perl环境 http://www.perl.org/get.html
下载percona-toolkit工具集合 https://www.percona.com/doc/percona-toolkit
ppm install DBI 依赖
ppm install DBD::mysql 安装 mysql驱动依赖
pt-online-schema-change h=127.0.0.1,u=root,D=mysqldemo,t=product_info --alter "modify product_name varchar(150) not null default '' " --execute
5.Mysql事物
1.查看数据库下面是否支持事务(InnoDB支持)? show engines;
2.查看mysql当前默认的存储引擎? show variables like '%storage_engine%';
3.查看某张表的存储引擎? show create table 表名 ;
4.对于表的存储结构的修改? 建立InnoDB 表:Create table .... type=InnoDB; Alter table table_name type=InnoDB;
5.1事务的特性
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
事务并发问题
脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
未提交读(READ UNCOMMITED)脏读
set SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
已提交读 (READ COMMITED)不可重复读
set SESSION TRANSACTION ISOLATION LEVEL read committed;
可重复读(REPEATABLE READ)
set SESSION TRANSACTION ISOLATION LEVEL repeatable read;
可串行化(SERIALIZABLE)
set SESSION TRANSACTION ISOLATION LEVEL serializable;
事务隔离级别为可重复读时,如果有索引(包括主键索引)的时候,以索引列为条件更新数据,会存在间隙锁间、行锁、页锁的问题,从而锁住一些行;如果没有索引,更新数据时会锁住整张表 事务隔离级别为串行化时,读写数据都会锁住整张表
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大,对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读取,而且具有较好的并发性能。
事物语法
开启事务 1、begin 2、START TRANSACTION(推荐) 3、begin work 事务回滚 rollback 事务提交 commit 还原点savepoint
6.逻辑设计
数据库设计的第一大范式
数据库表中的所有字段都只具有单一属性 单一属性的列是由基本数据类型所构成的 设计出来的表都是简单的二维表
数据库设计的第二大范式
要求表中只具有一个业务主键,也就是说符合第二范式的表不能存在非主键列只对部分主键的依赖关系
数据库设计的第三大范式
指每一个非非主属性既不部分依赖于也不传递依赖于业务主键,也就是在第二范式的基础上相处了非主键对主键的传递依赖
什么叫反范式化设计
反范式化是针对范式化而言得,在前面介绍了数据库设计得范式 所谓得反范式化就是为了性能和读取效率得考虑而适当得对数据库设计范式得要求进行违反 允许存在少量得冗余,换句话来说反范式化就是使用空间来换取时间
范式化设计优缺点
优点: 可以尽量得减少数据冗余
范式化的更新操作比反范式化更快
范式化的表通常比反范式化的表更小
缺点: 对于查询需要对多个表进行关联
更难进行索引优化
反范式化设计优缺点
优点: 可以减少表的关联 可以更好的进行索引优化
缺点: 存在数据冗余及数据维护异常 对数据的修改需要更多的成本
物理设计
物理设计
定义数据库、表及字段的命名规范 选择合适的存储引擎 为表中的字段选择合适的数据类型 建立数据库结构
定义数据库、表及字段的命名规范 数据库、表、字段的命名要遵守可读性原则 使用大小写来格式化的库对象名字以获得良好的可读性 例如:使用custAddress而不是custaddress来提高可读性。 数据库、表、字段的命名要遵守表意性原则 对象的名字应该能够描述它所表示的对象 例如: 对于表,表的名称应该能够体现表中存储的数据内容;对于存储过程 存储过程应该能够体现存储过程的功能。 数据库、表、字段的命名要遵守长名原则 尽可能少使用或者不使用缩写
为表中的字段选择合适的数据类型
当一个列可以选择多种数据类型时 优先考虑数字类型 其次是日期、时间类型 最后是字符类型 对于相同级别的数据类型,应该优先选择占用空间小的数据类型
7.慢查询
慢查询定义及作用 慢查询日志,顾名思义,就是查询慢的日志,是指mysql记录所有执行超过long_query_time参数设定的时间阈值的SQL语句的日志。该日志能为SQL语句的优化带来很好的帮助。默认情况下,慢查询日志是关闭的,要使用慢查询日志功能,首先要开启慢查询日志功能。
show VARIABLES like '%slow_query_log%' show VARIABLES like '%slow_query_log_file%' show VARIABLES like '%long_query_time%' show VARIABLES like '%log_queries_not_using_indexes%' show VARIABLES like 'log_output' ------------------------------------------------------ set global long_query_time=0; set GLOBAL slow_query_log = 1; set global log_output='FILE,TABLE'
常用配置
slow_query_log 启动停止技术慢查询日志
slow_query_log_file 指定慢查询日志得存储路径及文件(默认和数据文件放一起)
long_query_time 指定记录慢查询日志SQL执行时间得伐值(单位:秒,默认10秒)
log_queries_not_using_indexes 是否记录未使用索引的SQL log_output 日志存放的地方【TABLE】【FILE】【FILE,TABLE】
慢查询分析工具【mysqldumpslow】
语法 mysqldumpslow -s r -t 10 slow-mysql.log
-s order (c,t,l,r,at,al,ar)
c:总次数
t:总时间
l:锁的时间
r:总数据行
at,al,ar :t,l,r平均数 【例如:at = 总时间/总次数】
-t top 指定取前面几天作为结果输出
mysqldumpslow.pl -s t -t 10 D:DESKTOP-2EKGEE5-slow.log
慢查询分析工具【pt_query_digest】
pt-query-digest --explain h=127.0.0.1, u=root,p=password slow-mysql.log
汇总的信息【总的查询时间】、【总的锁定时间】、【总的获取数据量】、【扫描的数据量】、【查询大小】
汇总的信息【总的查询时间】、【总的锁定时间】、【总的获取数据量】、【扫描的数据量】、【查询大小】
Response: 总的响应时间。 time: 该查询在本次分析中总的时间占比。 calls: 执行次数,即本次分析总共有多少条这种类型的查询语句。 R/Call: 平均每次执行的响应时间。 Item : 查询对象
8.索引与执行计划
8.1索引是什么?
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。 可以得到索引的本质:索引是数据结构。
索引分类
普通索引:即一个索引只包含单个列,一个表可以有多个单列索引
唯一索引:索引列的值必须唯一,但允许有空值
复合索引:即一个索引包含多个列
聚簇索引(聚集索引):并不是一种单独的索引类型,而是一种数据存储方式。具体细节取决于不同的实现,InnoDB的聚簇索引其实就是在同一个结构中保存了B-Tree索引(技术上来说是B+Tree)和数据行。
非聚簇索引:不是聚簇索引,就是非聚簇索引 show global variables like "%datadir%";
基础语法
查看索引 SHOW INDEX FROM table_nameG
创建索引 CREATE [UNIQUE ] INDEX indexName ON mytable(columnname(length));
ALTER TABLE 表名 ADD [UNIQUE ] INDEX [indexName] ON (columnname(length))
删除索引 DROP INDEX [indexName] ON mytable;
执行计划
执行计划是什么 使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈 语法 Explain + SQL语句
8.2执行计划
执行计划-ID
select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序 三种情况 id相同,执行顺序由上至下 id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行 id相同不同,同时存在
id如果相同,可以认为是一组,从上往下顺序执行; 在所有组中,id值越大,优先级越高,越先执行
执行计划-select_type
执行计划-table
显示这一行的数据是关于哪张表的
执行计划-type
type显示的是访问类型,是较为重要的一个指标,结果值从最好到最坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
需要记忆的 system>const>eq_ref>ref>range>index>ALL
system 表只有一行记录(等于系统表),这是const类型的特列,平时不会出现,这个也可以忽略不计
const 表示通过索引一次就找到了 const用于比较primary key或者unique索引。因为只匹配一行数据,所以很快 如将主键置于where列表中,MySQL就能将该查询转换为一个常量
eq_ref 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描
ref 非唯一性索引扫描,返回匹配某个单独值的所有行. 本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体
range 只检索给定范围的行,使用一个索引来选择行。key 列显示使用了哪个索引 一般就是在你的where语句中出现了between、<、>、in等的查询 这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束语另一点,不用扫描全部索引。
all Full Table Scan,将遍历全表以找到匹配的行
执行计划-possible_keys
实际使用的索引。如果为NULL,则没有使用索引
查询中若使用了覆盖索引,则该索引和查询的select字段重叠
执行计划-key_len
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。在不损失精确性的情况下,长度越短越好 key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的
key_len表示索引使用的字节数, 根据这个值,就可以判断索引使用情况,特别是在组合索引的时候,判断所有的索引字段是否都被查询用到。 char和varchar跟字符编码也有密切的联系, latin1占用1个字节,gbk占用2个字节,utf8占用3个字节。(不同字符编码占用的存储空间不同)
字符类型-索引字段为char类型+不可为Null时
字符类型-索引字段为char类型+允许为Null时
索引字段为varchar类型+不可为Null时
varchar(n)变长字段+不允许Null=n*(utf8=3,gbk=2,latin1=1)+2
索引字段为varchar类型+允许为Null时
整数/浮点数/时间类型的索引长度
NOT NULL=字段本身的字段长度 NULL=字段本身的字段长度+1(因为需要有是否为空的标记,这个标记需要占用1个字节) datetime类型在5.6中字段长度是5个字节,datetime类型在5.5中字段长度是8个字节
key_len 总结
变长字段需要额外的2个字节(VARCHAR值保存时只保存需要的字符数,另加一个字节来记录长度(如果列声明的长度超过255,则使用两个字节),所以VARCAHR索引长度计算时候要加2),固定长度字段不需要额外的字节。 而NULL都需要1个字节的额外空间,所以索引字段最好不要为NULL,因为NULL让统计更加复杂并且需要额外的存储空间。 复合索引有最左前缀的特性,如果复合索引能全部使用上,则是复合索引字段的索引长度之和,这也可以用来判定复合索引是否部分使用,还是全部使用。
执行计划-ref
ref 显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值
由key_len可知t1表的idx_col1_col2被充分使用,col1匹配t2表的col1,col2匹配了一个常量,即 'ac'
执行计划-rows
ref 根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数
执行计划-Extra
Extra 包含不适合在其他列中显示但十分重要的额外信息
USING index 覆盖索引(Covering Index),一说为索引覆盖。 理解方式一:就是select的数据列只用从索引中就能够取得,不必读取数据行,MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件,换句话说查询列要被所建的索引覆盖。 理解方式二:索引是高效找到行的一个方法,但是一般数据库也能使用索引找到一个列的数据,因此它不必读取整个行。毕竟索引叶子节点存储了它们索引的数据;当能通过读取索引就可以得到想要的数据,那就不需要读取行了。一个索引包含了(或覆盖了)满足查询结果的数据就叫做覆盖索引。
注意: 如果要使用覆盖索引,一定要注意select列表中只取出需要的列,不可select *, 因为如果将所有字段一起做索引会导致索引文件过大,查询性能下降。
9.mysql优化
策略1.尽量全值匹配
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July';
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 25;
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 25 AND pos = 'dev';
策略2.最佳左前缀法则
如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列
策略3.不在索引列上做任何操作
不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
策略4.范围条件放最后
策略5.覆盖索引尽量用
尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *
策略6.不等于要甚用
mysql 在使用不等于(!= 或者<>)的时候无法使用索引会导致全表扫描
策略7.Null/Not 有影响
注意null/not null对索引的可能影响
策略8.Like查询要当心
like以通配符开头('%abc...')mysql索引失效会变成全表扫描的操作
策略9.字符类型加引号
字符串不加单引号索引失效
策略10.OR改UNION效率高
葵花宝典
全职匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
LIKE百分写最右,覆盖索引不写*;
不等空值还有OR,索引影响要注意;
VAR引号不可丢, SQL优化有诀窍。
insert语句优化
insert语句优化; 提交前关闭自动提交 尽量使用批量insert语句 可以使用MyISAM存储引擎
LOAD DATA INFLIE; 使用LOAD DATA INFLIE ,比一般的insert语句快20倍
select * into OUTFILE 'D:\product.txt' from product_info
load data INFILE 'D:\product.txt' into table product_info