暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL DBA的自我修养(二十三)

记忆乘凉 2017-01-10
266

232:详细描述一下不走索引的一些情况以及“坑”,进行一次演讲。

(由于该题篇幅太长,文章字数限制,在这里只展示了小标题,随后会贴出此题详细内容专题)

1. 没有查询条件,或者查询条件没有建立索引

2. 在查询条件上没有使用引导列
3. 查询的数据量是大表的大部分,应该是30%以上(主键索引除外) -----可以走全表扫描
4. 索引本身失效
5. 查询条件使用函数在索引列,或者对索引列进行运算,运算包括(+ - * / !等)

6. 对小表查询
7. 提示不使用索引(也就是在select的时候忽略索引)
8. 统计数据不真实

9. CBO计算走索引花费过大的情况
10. 隐式转换导致索引失效,这一点应当引起重视,也是开发中经常会犯的错

11.不等于<>不一定不走索引

12. like 和<>"%_" 百分号在前;not like ,不管是%放在后面还是前面

13. 表没分析
14. not in,not exist

15. 当变量采用的是times变量,而表的字段采用的是data变量时,或相反情况

16. B-tree索引 is null,is not null处理的不是很好

 


233:识别 ddl 操作,确认哪些操作属于 ddl。

DDL(datedefinition languages)语句:数据定义了语言,定义了数据库、表、索引等对象的定义。常用的语句包括create、drop、alter等

1.创建数据库

mysql> createdatabase test2 ;

Query OK, 1 rowaffected (0.00 sec)

row affected表示有一行记录受到影响

sec表示这个操作的执行时间

2.查看数据库

mysql> showdatabases;

+--------------------+

| Database           |

+--------------------+

|information_schema |

| mysql              |

|performance_schema |

| sakila             |

| test               |

| test1              |

| test2              |

+--------------------+

7 rows in set(0.01 sec)

information_schema:存储了系统中一些对象信息,如:用户表信息,试图信息,各种数据库变量状态、字符集信息等

mysql:主要是用户的相关权限信息

performance_schema:记录系统性能的数据库。通过performance_schema变更决定是否开启,默认不是开启的

test:测试数据库

注意:数据库和表名是否区别大小写由一个参数决定:

lower_case_table_mames

当值为1时,表名和库名对大小写不敏感,用小写保存在硬盘上;设置为0时,按指定的名字保存在硬盘上,大小写敏感

3.选择数据库

mysql> usesakila;

Database changed

4.查看表

mysql> showtables;

+----------------------------+

|Tables_in_sakila           |

+----------------------------+

| actor                      |

|actor_info                 |

| address                    |

| category                   |

| city                       |

| country                    |

| customer                   |

|customer_list              |

| film                       |

|film_actor                 |

|film_category              |

| film_list                  |

| film_text                  |

| inventory                  |

| language                   |

|nicer_but_slower_film_list |

| payment                    |

| rental                     |

|sales_by_film_category     |

|sales_by_store             |

| staff                      |

|staff_list                 |

| store                      |

+----------------------------+

23 rows in set(0.00 sec)

5.删除数据库

mysql> dropdatabase test2 ;

Query OK, 0 rowsaffected (0.04 sec)

删除数据库后,数据库下面所有的表都会被删除。

6.创建表

语法:

create tabletablename

    column_name1 column_type1 constrains

    column_name2 column_ytpe2 constraints

    ......

   column_nameN colume_tupeN constraints);

column_name      字段名称

column_type        字段类型

constraints           字段的约束

注意:表名额可以包括字母、数字,下划线和美元符号,但不能完全是数字。

取表名和数据库名的原则是看其名和其意

mysql> createtable emp(

    -> name varchar(10) ,

    -> hirdate date,

    -> sal decimal(10,2),

    -> depton int);

Query OK, 0 rowsaffected (0.02 sec)

 

7.查看表结构

desc tablename

mysql> descemp ;

+---------+---------------+------+-----+---------+-------+

| Field   | Type          | Null | Key | Default | Extra |

+---------+---------------+------+-----+---------+-------+

| name    | varchar(10)   | YES |     | NULL    |      |

| hirdate |date          | YES  |     |NULL    |       |

| sal     | decimal(10,2) | YES  |     |NULL    |       |

| depton  | int(11)       | YES |     | NULL    |      |

+---------+---------------+------+-----+---------+-------+

4 rows in set(0.01 sec)

Filed:字段名称

Type:字段类型

Null:是否可以为空

Key:是否有索引

Default:是否有默认值

8.查看具体表

show createtable tablename

mysql> showcreate table emp \G

***************************1. row ***************************

       Table: emp

Create Table:CREATE TABLE `emp` (

  `name` varchar(10) DEFAULT NULL,

  `hirdate` date DEFAULT NULL,

  `sal` decimal(10,2) DEFAULT NULL,

  `depton` int(11) DEFAULT NULL

) ENGINE=InnoDBDEFAULT CHARSET=utf8

1 row in set(0.00 sec)

除了看到表的定义外,可以看到表使用的存储引擎engine=innodb,使用的字符集charset=utf8。"\G"的意思是使得记录能够按照竖排显示,更易阅读

9.约束

[NOT NULL |NULL]                        是否可以为空

[DEFAULEdefault_value]                是否有默认值

[AUTP_INCREMENT]                       是否是自动增长

[UNIQUE [KEY] |[RPIMARY] KEY]    是否是主键

[CONMENT'string']                        注释

mysql> CREATETABLE city(

->city_id intNOT NULL AUTO_inCREMENt,

->cityvarchar(50) NOT NULL comment 'city name',

->country_namevarchar(20) NOT NULL default 'china',

->KEY(city_id)

->);

Query OK, 0 rowsaffected (0.01 sec)

 

10.插入数据

mysql> insertinto city(city) values('beijing');

Query OK, 1 rowaffected (0.01 sec)

11.创建相似表

create tabletable_name like table_name1;

mysql> createtable city_bak like city;

Query OK, 0 rowsaffected (0.02 sec)

12.增加表字段

语法

alter tabletablename ADD col_name column_definition [FIRST | AFTER col_name]

mysql> altertable emp add column age int(3);

Query OK, 0 rowsaffected (0.09 sec)

Records: 0  Duplicates: 0 Warnings: 0

mysql> descemp;

+---------+---------------+------+-----+---------+-------+

| Field   | Type          | Null | Key | Default | Extra |

+---------+---------------+------+-----+---------+-------+

| name    | varchar(10)   | YES |     | NULL    |      |

| hirdate |date          | YES  |     |NULL    |       |

| sal     | decimal(10,2) | YES  |     |NULL    |       |

| depton  | int(11)       | YES |     | NULL    |      |

| age     | int(3)        | YES |     | NULL    |      |

+---------+---------------+------+-----+---------+-------+

5 rows in set(0.00 sec)

13.修改字段类型

语法:

alter tabletablename MODIFY col_name column_definition [FIRST | AFTER col_name]

mysql> altertable emp modify name varchar(20);

Query OK, 0 rowsaffected (0.01 sec)

Records: 0  Duplicates: 0 Warnings: 0

mysql> descemp;

+---------+---------------+------+-----+---------+-------+

| Field   | Type          | Null | Key | Default | Extra |

+---------+---------------+------+-----+---------+-------+

| name    | varchar(20)   | YES |     | NULL    |      |

| hirdate |date          | YES  |     |NULL    |       |

| sal     | decimal(10,2) | YES  |     |NULL    |       |

| depton  | int(11)       | YES |     | NULL    |      |

| age     | int(3)        | YES |     | NULL    |      |

+---------+---------------+------+-----+---------+-------+

5 rows in set(0.00 sec)

14.修改字段排列顺序

mysql> altertable emp modify hirdate date first;

Query OK, 0 rowsaffected (0.02 sec)

Records: 0  Duplicates: 0 Warnings: 0

mysql> descemp;

+---------+---------------+------+-----+---------+-------+

| Field   | Type          | Null | Key | Default | Extra |

+---------+---------------+------+-----+---------+-------+

| hirdate |date          | YES  |     |NULL    |       |

| name    | varchar(20)   | YES |     | NULL    |      |

| sal     | decimal(10,2) | YES  |     |NULL    |       |

| depton  | int(11)       | YES |     | NULL    |      |

| age     | int(3)        | YES |     | NULL    |      |

+---------+---------------+------+-----+---------+-------+

5 rows in set(0.00 sec)

15.删除表字段

语法:

alter tabletablename DROP col_name

mysql> altertable emp drop age;

Query OK, 0 rowsaffected (0.02 sec)

Records: 0  Duplicates: 0 Warnings: 0

mysql> descemp;

+---------+---------------+------+-----+---------+-------+

| Field   | Type          | Null | Key | Default | Extra |

+---------+---------------+------+-----+---------+-------+

| hirdate |date          | YES  |     |NULL    |       |

| name    | varchar(20)   | YES |     | NULL    |      |

| sal     | decimal(10,2) | YES  |     |NULL    |       |

| depton  | int(11)       | YES |     | NULL    |      |

+---------+---------------+------+-----+---------+-------+

4 rows in set(0.00 sec)

16.字段改名

alter tabletablename CHANGE old_col_name new_col_name column_definition [FIRST |AFTERcol_name]

mysql> altertable emp change deption depton1 int(11);

Query OK, 0 rowsaffected (0.02 sec)

Records: 0  Duplicates: 0 Warnings: 0

mysql> descemp;

+---------+---------------+------+-----+---------+-------+

| Field   | Type          | Null | Key | Default | Extra |

+---------+---------------+------+-----+---------+-------+

| hirdate |date          | YES  |     |NULL    |       |

| name    | varchar(20)   | YES |     | NULL    |      |

| sal     | decimal(10,2) | YES  |     |NULL    |       |

| depton1 |int(11)       | YES  |     |NULL    |       |

+---------+---------------+------+-----+---------+-------+

4 rows in set(0.00 sec)

注意:change和modify都可以修改表的定义,不同的是change后面需要写两次列名。但是change的优点是可以修改列名称,modify则不能。

change/first/after这些关键字是MySQL在标准SQL上的扩展,在其他数据库上不适用。

17.更改表名

语法:

alter tabletablename RENAME [TO] new_tbl_name;

mysql> altertable emp rename emp1;

Query OK, 0 rowsaffected (0.00 sec)

 

18.删除表

语法:

drop tabletablename;

mysql> droptable emp;

Query OK, 0 rowsaffected (0.00 sec)

19.创建索引

语法:

CREATE[UNIQUE|FULLTEXT|SPATIAL] INDEX index_name

    [USING index_type]

    ON tbl_name (index_col_name,...)

index_col_name:

    col_name [(length)] [ASC | DESC]

mysql> createindex ind_emp_dept using btree on emp(depton);

Query OK, 0 rowsaffected (0.10 sec)

Records: 0  Duplicates: 0 Warnings: 0

注意:索引起名最好以ind开头或者idx等类似index开头,做到看其名字知其意,创建索引默认是BTREE索引

使用altertable也可以创建和删除索引

20.删除索引

语法:

drop indexindex_name on table_name;

mysql> dropindex ind_emp_dept on emp;

Query OK, 0 rowsaffected (0.06 sec)

Records: 0  Duplicates: 0 Warnings: 0

21.创建视图

视图是一种虚拟存在的表,对于使用视图的用户来说是透明的。视图在数据库中并不占用存储空间。在使用过程中的数据是从实际存在的表动态生成的。

简单:使用视图的用户完全不用关心后面对应的表机构和筛选条件,对用户来说是已经过滤好的复合条件的结果集

安全:使用视图的用户只能访问他们被允许查询的结果集。

语法:

CREATE [ORREPLACE]

VIEW view_name[(column_list)]

ASselect_statement

[WITH [CASCADED| LOCAL] CHECK OPTION];

其中,[WITH[CASCADED | LOCAL] CHECK OPTION],决定了是否允许更新数据使用记录不再满足视图的条件。

*LOCAL是只要满足本视图的条件就可以更新

*CASCADED 是必须满足所有针对创建该视图的相关视图的条件才可以更新,这是默认选项

 


234:ddl 的风险,如何对 ddl 的风险进行测试。

MySQL数据库在执行DDL操作时会锁表,在数据量大的情况下会消耗特别多的资源,在实际生产中会造成阻塞。可以通过压力测试进行生产上的模拟,然后连接一个客户端执行DDL操作,并观察数据库的性能状态。

 


235:识别 ddl 对应的算法和锁,对于锁的深度认识,特别是对于 lock=none 的真相。

当对一个表做DDL的时候:

    1.查看表上是否有TM:RX锁,如果有,则等待对应的事务完成。(如果之前的RX锁一直不释放,阻塞后面大量新来的RX,而不是转换者队列的,可能导致数据库hang住挂起)

    2.之后过来想做DML的进程都在后面排队

    3.事务完成后,释放行锁,释放TM:RX,随后就可以加上TM:X锁

    4.对表进行DDL操作

当在表上建索引的时候:会给表加上S锁,任何人不能修改。

 


236:online ddl 对应的坑。

海量的 io、短暂的加上 exclusive 或者 shared 锁。

Online DDL有 LOCK 选项控制是否锁表,根据不同的DDL操作类型有不同的表现:默认mysql尽可能不去锁表,但是像修改主键这样的昂贵操作不得不选择锁表。

1.LOCK=NONE,即DDL期间允许并发读写涉及的表,比如为了保证 ALTER TABLE 时不影响用户注册或支付,可以明确指定,好处是如果不幸该alter语句不支持对该表的继续写入,则会提示失败,而不会直接发到库上执行。ALGORITHM=COPY默认LOCK级别;

2.LOCK=SHARED,即DDL期间表上的写操作会被阻塞,但不影响读取。

3.LOCK=DEFAULT,让mysql自己去判断lock的模式,原则是mysql尽可能不去锁表

4.LOCK=EXCLUSIVE,即DDL期间该表不可用,堵塞任何读写请求。如果你想alter操作在最短的时间内完成,或者表短时间内不可用能接受,可以手动指定。

但是有一点需要说明,无论任何模式下,online ddl开始之前都需要一个短时间排它锁(exclusive)来准备环境,所以alter命令发出后,会首先等待该表上的其它操作完成,在alter命令之后的请求会出现等待waiting meta data lock。同样在ddl结束之前,也要等待alter期间所有的事务完成,也会堵塞一小段时间。所以尽量在ALTER TABLE之前确保没有大事务在执行,否则一样出现连环锁表。

 


237:开发经常会对表进行 ddl,如何规范 ddl 操作,写出一个规范的流程

提交给 ddl 需求给 dba

限制开发人员对数据库的 ddl 权限

dba 进行测试:io 测试、时间测试、是否支持 in place、none,显式的加上lock none

dba 形成操作规范和风向评估报告,走流程审批进行相关的操作

 


238:分区表的四大好处。

1.   易维护,数据量小,可以对单独的分区进行相关操作,备份和恢复方便。

2.   减少IO,分区表的数据文件独立成为ibd,可以放在不同的物理磁盘上,减轻磁盘负载。

3.   减少单表索引和锁的互斥。

4.   性能提升,提高查询效率,数据独立和索引独立。



239:建立一个以年和以天分区的表,要求带上maxvalue

CREATE TABLE employees (

idINT NOT NULL,

fnameVARCHAR(30),

lnameVARCHAR(30),

hiredDATE NOT NULL DEFAULT '1970-01-01',

separatedDATE NOT NULL DEFAULT '9999-12-31',

job_codeINT,

store_idINT

)

分区列 separated.

ENGINE=INNODB

PARTITON BYRANGE (YEAR(SEPARATED)) (

PARTTION p2014VALUE LESS THEN (2015),

PARTTION p2015VALUE LESS THEN (2016),

PARTTION p2016VALUE LESS THEN (2017),

PARTTION p2017VALUE LESS THEN MAXVALUE

);

 


240:建立一个人口表,要求按照出生的省份做一个列表分区,每一个省一个分区。

create tablepeople(

id int not null,

name varchar(20)not null,

born data,

provincevarchar(10) not null,

) ENGINE=INNODB

PARTITON BYLIST(PROVINCE) (

PARTTION p0VALUE IN (‘SHANDONG’),

PARTTION p1VALUE IN (‘BEIJING’)

……

);

 


241:5.6 支持 hash 分区,对于 240建立的人口表,进一步细分出来 hash 分区,每一个省份的分区在出生年月这个列上建立 16 个子分区。

ENGINE=INNODB

PARTITION BYHASH(data)

PARTITION 16;


文章转载自记忆乘凉,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论