mysql 知识点

tech2022-10-13  109

设置序列的开始 1.drop table tbl_nm; create table tbl_nm( id int unsigned not null auto_increment, )engine=innodb auto_increment=100 default charset=utf8; 2.alter table tbl_nm auto_increment=200;

创建临时表 create TEMPORARY table temp_test ( id int unsigned not null primary key auto_increment, name char(20) not null default ‘’ )engine=innodb auto_increment=200 charset=utf8;

insert into temp_test values(NULL, ‘lisi’); //可以查询临时表记录,show tables无法查看到临时表 select * from temp_test; //当前会话接收,自动删除临时表,也可主动删除临时表 drop table temp_test;

表复制 1.create table tbl_nm (select * from tbl_nm) 表结构和记录会同步,但索引不会被创建 //表克隆 1.show create table source_tbl_nm 获取原表Create Table创表sql; 2.修改sql中表明为目的表名称 3.原表数据导入到目的表中 insert into dest_tbl_nm values (‘cl1’,‘cl2’) select * from source_tbl_nm;

预处理 1.定义预处理语句:PREPARE stmt_nm FROM preparable_stmt; 2.执行预处理语句:EXECUTE stmt_nm [USING @var_nm1 [, @var_nm2]…]; 3.删除或释放定义:DEALLOCATE | DROP PREPARE stmt_nm;

通过max_prepared_stmt_count变量来控制全局最大的存储的预处理语句 show variables like ‘max_prepared%’;

预处理编译sql是占用资源的,在使用后需要及时DEALLOCATE PREPARE 释放资源

预编译效率 客户端通过发送一条sql语句到服务器,需要经过解析器(词法和语法)、 预处理器(检测解析器生成的解析树,检测表名、列表是否存在、检查名字和别名没有歧义并检测权限)、 优化器(找出最优的执行路径,生成执行计划) 查询执行引擎执行查询并返回给客户端

若果需要多次执行insert、update、delete语句,但是每次插入的值不同,mysql服务器 也需要经过解析器、预处理器、优化器,就会浪费太多时间 若果使用预编译功能,sql语句只会一次的校验和编译,效率比较高

实例 prepare stmt_nm from ‘select * from employees where employee_id=?’; set @var=100; execute stmt_nm using @var; set @var=101; execute stmt_nm using @var; deallocate prepare stmt_nm;

预处理sql注意点 1.stmt_nm作为preparable_stmt的接收者,唯一标识,不区分大小写 2.preparable_stmt语句中的?是个占位符,所代表的是一个字符串 不需要将?用引号包含起来 3.定义一个已存在的stmt_nm,原有的将被立即释放,相当于变量的重新赋值 4.prepare stmt_nm的作用域是session级

预编译的好处 1.预编译之后的sql多数情况下可以直接执行,DBMS不需要再次编译 2.越复杂的SQL,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作; 3.相同的预编译sql可以重复利用 4.可以将这类sql语句中的值用占位符替代,不需要每次编译,可以直接执行 只需要执行的时候,直接将每次请求的不同值设置到占位符的位置 5.预编译可以视为将sql语句模块化或者说参数化

隔离级别几种问题

脏读: 当前事务A中可以读到其他事务B未提交的数据(脏数据) , 这种现象是脏读

不可重复读: 在事务 A 中先后两次读取同一个数据, 两次读取的结果不一样, 这种现象称为不可重复读。 脏读与不可重复读的区别在于: 前者读到的是其他事务未提交的数据,后者读到的是其他事务已提交的数据

幻读: 在事务 A 中按照某个条件先后两次查询数据库, 两次查询结果的条数不同,这种现象称为幻读。 不可重复读与幻读的区别可以通俗的理解为: 前者是数据变了, 后者是数据的行数变了

不可重复读和幻读到底有什么区别呢? (1) 不可重复读是读取了其他事务更改的数据, 针对 update 操作 解决: 使用行级锁, 锁定该行, 事务 A 多次读取操作完成后才释放该锁, 这个时候才允许其他事务更改刚才的数据。 (2) 幻读是读取了其他事务新增的数据, 针对 insert 与 delete 操作 解决: 使用表级锁, 锁定整张表, 事务 A 多次读取数据总量之后才释放该锁, 这个时候才允许其他事务新增数据。 幻读和不可重复读都是指的一个事务范围内的操作受到其他事务的影响了。只不过幻读是重点在插入和删除, 不可重复读重点在修改

存储引擎 show engines; 查看默认存储引擎 show variables like ‘%storage_engine’ 设置存储引擎 1.create table ( id int not null primary key auto_increment )engine=innodb(不写默认innodb) 2.配置文件修改:default-storage-engine = engine 3.alter命令修改:alter table tbl_nm engine=myisam;

mysql优化 1.sql语句和索引的优化 2.数据库表结构的优化 3.系统配置的优化 4.硬件的优化

sql优化 1.对查询进行优化, 应尽量避免全表扫描, 首先应考虑在 where 及 order by 涉及的列上 建立索引。 2.应尽量避免在 where 子句中使用!=或<>操作符, 否则将引擎放弃使用索引而进行全表扫 描。 3.应尽量避免在 where 子句中对字段进行 null 值判断, 否则将导致引擎放弃使用索引而 进行全表扫描

select id from t where num is null 可以在 num 上设置默认值 0, 确保表中 num 列没有 null 值, 然后这样查询: select id from t where num=0 4.应尽量避免在 where 子句中使用 or 来连接条件, 否则将导致引擎放弃使用索引而进行 全表扫描, 如: select id from t where num=10 or num=20 可以这样查询: select id from t where num=10 union all select id from t where num=20 5.下面的查询也将导致全表扫描: select id from t where name like ‘%abc%’ 若要提高效率, 可以考虑全文检索。 6.in 和 not in 也要慎用, 否则会导致全表扫描, 如: select id from t where num in(1,2,3) 对于连续的数值, 能用 between 就不要用 in 了: select id from t where num between 1 and 3 7.如果在 where 子句中使用参数, 也会导致全表扫描。 因为 SQL 只有在运行时才会解析局 部变量, 但优化程序不能将访问计划的选择推迟到运行时; 它必须在编译时进行选择。 然而, 如果在编译时建立访问计划, 变量的值还是未知的, 因而无法作为索引选择的输入项。 如下 面语句将进行全表扫描: select id from t where num=@num 可以改为强制查询使用索引: select id from t with(index(索引名)) where num=@num 8.应尽量避免在 where 子句中对字段进行表达式操作, 这将导致引擎放弃使用索引而进行 全表扫描。 如: select id from t where num/2=100 应改为: select id from t where num=100*2 9.应尽量避免在 where 子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表 扫描。 如: select id from t where substring(name,1,3)=‘abc’–name 以 abc 开头的 id select id from t where datediff(day,createdate,‘2005-11-30’)=0–'2005-11-30’生成 的 id 应改为: select id from t where name like ‘abc%’ select id from t where createdate>=‘2005-11-30’ and createdate<‘2005-12-1’ 10.不要在 where 子句中的“=” 左边进行函数、 算术运算或其他表达式运算, 否则系统将 可能无法正确使用索引。 11.在使用索引字段作为条件时, 如果该索引是复合索引, 那么必须使用到该索引中的第一 个字段作为条件时才能保证系统使用该索引, 否则该索引将不会被使用, 并且应尽可能的让 字段顺序与索引顺序相一致。 12.不要写一些没有意义的查询, 如需要生成一个空表结构: select col1,col2 into #t from t where 1=0

这类代码不会返回任何结果集, 但是会消耗系统资源的, 应改成这样: create table #t(…) 13.很多时候用 exists 代替 in 是一个好的选择: select num from a where num in(select num from b) 用下面的语句替换: select num from a where exists(select 1 from b where num=a.num) 14.并不是所有索引对查询都有效, SQL 是根据表中数据来进行查询优化的, 当索引列有大 量数据重复时, SQL 查询可能不会去利用索引, 如一表中有字段 sex, male、 female 几乎各 一半, 那么即使在 sex 上建了索引也对查询效率起不了作用。 15.索引并不是越多越好, 索引固然可以提高相应的 select 的效率, 但同时也降低了 insert 及 update 的效率, 因为 insert 或 update 时有可能会重建索引, 所以怎样建索 引需要慎重考虑, 视具体情况而定。 一个表的索引数最好不要超过 6 个, 若太多则应考虑一 些不常使用到的列上建的索引是否有必要。 16.应尽可能的避免更新 clustered 索引数据列, 因为 clustered 索引数据列的顺序就是 表记录的物理存储顺序, 一旦该列值改变将导致整个表记录的顺序的调整, 会耗费相当大的 资源。 若应用系统需要频繁更新 clustered 索引数据列, 那么需要考虑是否应将该索引建 为 clustered 索引。 17.尽量使用数字型字段, 若只含数值信息的字段尽量不要设计为字符型, 这会降低查询和 连接的性能, 并会增加存储开销。 这是因为引擎在处理查询和连接时会逐个比较字符串中每 一个字符, 而对于数字型而言只需要比较一次就够了。 18.尽可能的使用 varchar/nvarchar 代替 char/nchar , 因为首先变长字段存储空间小, 可以节省存储空间, 其次对于查询来说, 在一个相对较小的字段内搜索效率显然要高些。 19.任何地方都不要使用 select * from t , 用具体的字段列表代替“*” , 不要返回用不 到的任何字段。 20.尽量使用表变量来代替临时表。 如果表变量包含大量数据, 请注意索引非常有限(只有 主键索引) 。 21.避免频繁创建和删除临时表, 以减少系统表资源的消耗。 22.临时表并不是不可使用, 适当地使用它们可以使某些例程更有效, 例如, 当需要重复引 用大型表或常用表中的某个数据集时。 但是, 对于一次性事件, 最好使用导出表。 23.在新建临时表时, 如果一次性插入数据量很大, 那么可以使用 select into 代替 create table, 避免造成大量 log , 以提高速度; 如果数据量不大, 为了缓和系统表的资源, 应先 create table, 然后 insert。 24.如果使用到了临时表, 在存储过程的最后务必将所有的临时表显式删除, 先 truncate table , 然后 drop table , 这样可以避免系统表的较长时间锁定。 25.尽量避免使用游标, 因为游标的效率较差, 如果游标操作的数据超过 1 万行, 那么就应 该考虑改写。 26.使用基于游标的方法或临时表方法之前, 应先寻找基于集的解决方案来解决问题, 基于 集的方法通常更有效。 27.与临时表一样, 游标并不是不可使用。 对小型数据集使用 FAST_FORWARD 游标通常要优 于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合 计” 的例程通常要比使用游标执行的速度快。 如果开发时间允许, 基于游标的方法和基于集 的方法都可以尝试一下, 看哪一种方法的效果更好。 28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON , 在结束时设置 SET NOCOUNT OFF 。 无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。

29.尽量避免向客户端返回大数据量, 若数据量过大, 应该考虑相应需求是否合理。 30.尽量避免大事务操作, 提高系统并发能力

表结构优化 1.使用可以存下你的数据的最小的数据类型 2.使用简单的数据类型,int要比varchar类型 在mysql处理上简单 3.尽可能的使用not null定义字段 4.尽量少用text类型,非用不可时最好考虑分表

表垂直拆分:吧很多列的表拆分成多个表,解决表的宽度问题 1.把不常用的字段单独存放到一个表中 2.把大字段独立存放到一个表中 3.把经常一起使用的字段放到一起

水平拆分:解决单表的数据量过大问题,水平拆分的 每个表结构一致

最新回复(0)