添加表字段
alter table table_name add column temperature varchar(10) comment '温度' ;
删除表字段
alter table id_name drop column age,drop column address;
修改表字段
- 修改字段类型
#alter table 表名 modify column 字段名 新数据类型; alter table user modify column money double(10,7)
- 修改默认值
#alter table 表名 alter column 字段名 drop default; (若本身存在默认值,则先删除) #alter table 表名 alter column 字段名 set default 默认值;(若本身不存在则可以直接设定) alter table user alter column create_time set default CURRENT_TIMESTAMP
- 修改注释
# alter table 表名 modify column 字段名 数据类型 comment '修改后的字段注释'; alter table user modify column create_time datetime comment '创建时间' #注意如果有默认值的话,要把默认值也加上了,不加的话,修改后就没有默认值了
# 一次性都修改
ALTER TABLE 表名 MODIFY COLUMN 字段名 新数据类型 新类型长度 新默认值 新注释; -- COLUMN可以省略
alter table user modify column money double(10,7) DEFAULT NULL COMMENT '收入';
mysql修改字段名(重命名):
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 新数据类型;
alter table table1 change column1 column1 varchar(100) DEFAULT 1.2 COMMENT '注释'; -- 正常,此时字段名称没有改变,能修改字段类型、类型长度、默认值、注释
alter table table1 change column1 column2 decimal(10,1) DEFAULT NULL COMMENT '注释' -- 正常,能修改字段名、字段类型、类型长度、默认值、注释
alter table table1 change column2 column1 decimal(10,1) DEFAULT NULL COMMENT '注释' -- 正常,能修改字段名、字段类型、类型长度、默认值、注释
alter table table1 change column1 column2; -- 报错
修改表名
ALTER TABLE user10 RENAME TO user11;
修改表注释
# alter table 表名 comment '修改后的表的注释';
alter table user comment '用户表'
char 和varchar的区别
char:定长,效率高,一般用于固定长度的表单提交数据存储 ;例如:身份证号,手机号,电话,密码等
varchar:不定长,效率偏低
获取时间戳,单位是秒(s)
select unix_timestamp()
在navicat中查看数据库大小
- 1、进入information_schema 数据库(存放了其他的数据库的信息)
- 2、查询所有数据库的大小
select concat(round(sum(DATA_LENGTH/1024/1024),2),'MB') as data from TABLES;
- 3、查询指定数据库大小
select concat(round(sum(DATA_LENGTH/1024/1024),2),'MB') as data from TABLES
WHERE TABLE_SCHEMA = 'bmt-oauth'
- 4、查询指定数据库中指定表的大小
select concat(round(sum(DATA_LENGTH/1024/1024),2),'MB') as data from TABLES
WHERE TABLE_SCHEMA = 'bmt-oauth' AND TABLE_NAME='sys_user'
- 5、查看指定数据库指定表单的其他大小
select
concat(round(sum(DATA_LENGTH/1024/1024),2),'MB') as data_size,
concat(round(sum(MAX_DATA_LENGTH/1024/1024),2),'MB') as max_data_size,
concat(round(sum(INDEX_LENGTH/1024/1024),2),'MB') as index_size,
concat(round(sum(DATA_FREE/1024/1024),2),'MB') as data_free
from TABLES
WHERE TABLE_SCHEMA = 'bmt-oauth' AND TABLE_NAME='sys_user'
添加索引
- 普通索引
alter table test add index index_name(name) USING BTREE
- 唯一索引
alter table test add unique index index_name(name) USING BTREE
- 全文索引
alter table test add fulltext index index_name(name) USING BTREE
- 多列索引、组合索引、复合索引
alter table test add index index_name(name,age) USING BTREE
注:name,age为表中字段名称
常用函数
- 替换字符串 REPLACE
update 表名 set 字段名=REPLACE (字段名,'原来的值','要修改的值')
update aaa set ac_name = REPLACE(ac_name,'积分星球','积分中心') where ac_name like '%积分星球%';
存在,则更新,不存在则插入
某些情况下,比如同步数据,批量 插入数据,我们会有一种需求,
当主键或者unique索引没有冲突的时候,直接执行插入操作,如果有冲突则不做任何操作,避免重复插入
即,如果插入的数据会导致UNIQUE索引或PRIMARY KEY发生冲突/重复,则执行更新操作
- on duplicate key update
如果指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,则执行UPDATE操作
如果行作为新记录被插入(没有冲突),则受影响行的值为1;
INSERT INTO `wasabi`.`experiment_user_index`(`user_id`, `context`, `app_name`, `experiment_id`) VALUES ('1', 'DEV', 'a2' ,'c083afde-951e-4356-bde3-f79dfb322b82')
ON DUPLICATE KEY UPDATE context = 'PROD'
> Affected rows: 1
> 时间: 0.062s
如果原有的记录被更新(有冲突),则受影响行的值为2。
INSERT INTO `wasabi`.`experiment_user_index`(`user_id`, `context`, `app_name`, `experiment_id`) VALUES ('11a', 'DEV', 'a2' ,'c083afde-951e-4356-bde3-f79dfb322b82')
ON DUPLICATE KEY UPDATE context = 'PROD'
> Affected rows: 2
> 时间: 0.062s
- replace into
首先尝试插入数据到表中, 1. 如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据。 2. 否则,直接插入新数据。
replace into tbl_name(col_name, ...) values(...)
replace into tbl_name(col_name, ...) select ...
replace into tbl_name set col_name=value, ...
-
性能
在数据库数据量很少的时候, 这两种方式都很快,无论是直接的插入还是有冲突时的更新,都不错,但在数据库表的内容数量比较大(如百万级)的时候,两种方式就不太一样了,首先是直接的插入操作,两种的插入效率都略低, 比如直接向表里插入1000条数据(百万级的表(innodb引擎)),二者都差不多需要5,6甚至十几秒。究其原因,我的主机性能是一方面,但在向大数据表批量插入数据的时候,每次的插入都要维护索引的, 索引固然可以提高查询的效率,但在更新表尤其是大表的时候,索引就成了一个不得不考虑的问题了。
其次是更新表,这里的更新的时候是带主键值的(因为我是从另一个表获取数据再插入,要求主键不能变) 同样直接更新1000条数据, replace的操作要比insert on duplicate的操作低太多太多, 当insert瞬间完成(感觉)的时候,replace要7,8s, replace慢的原因在于,当更新数据的时候,要先删除旧的,然后插入新的,在这个过程中,还要重新维护索引,所以速度慢,但为何insert on duplicate的更新却那么快呢。 在向老大请教后,终于知道,insert on duplicate 的更新操作虽然也会更新数据,但其对主键的索引却不会有改变,也就是说,insert on duplicate 更新对主键索引没有影响.因此对索引的维护成本就低了一些(如果更新的字段不包括主键,那就要另说了)。
存在,则不做操作,不存在则插入
某些情况下,比如同步数据,批量 插入数据,我们会有一种需求,
当主键或者unique索引没有冲突的时候,直接执行插入操作,如果有冲突则不做任何操作,避免重复插入
即,如果插入的数据会导致UNIQUE索引或PRIMARY KEY发生冲突/重复,则忽略此次操作/不插入数据
//插入成功
INSERT IGNORE INTO `wasabi`.`experiment_user_index`(`user_id`, `context`, `app_name`, `experiment_id`) VALUES ('0', 'DEV', 'a2' ,'c083afde-951e-4356-bde3-f79dfb322b82')
> Affected rows: 1
> 时间: 0.062s
//有重复,忽略不做操作
INSERT IGNORE INTO `wasabi`.`experiment_user_index`(`user_id`, `context`, `app_name`, `experiment_id`) VALUES ('0', 'PROD', 'a2' ,'c083afde-951e-4356-bde3-f79dfb322b82')
> Affected rows: 0
> 时间: 0.061s
查询当前数据库有多少表,每张表多少条数据
- 模糊查询:通过MySQL自带的统计信息
SELECT TABLE_NAME,TABLE_ROWS FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '库名' ORDER BY TABLE_ROWS DESC
注:可以同时统计库内的多张表,但是数据并不是很精确,通常比实际数据要少一点,但是对于精确性要求不高的话,是个很实用的方法,性能很好,毕竟不用扫描全表
- 精确查询:
select count(*) from tableName
- 多张表同时count
分库分表后,如果需要直接在navicat中查询多张表中的统计次数,每张表单独count查询太麻烦,也不利于统计。(当然,如果公司有自己的SQL平台,支持分库分表查询的话,那就不用这么麻烦了)
比如,我现在需要从xxx_user_0 到 xxx_user_9 这些表中统计user_id总数,那么可以使用union all 连接多张表,然后sum 累加统计
SELECT sum(cnt) FROM(
SELECT count(user_id) as cnt FROM xxx_user_0 WHERE CHAR_LENGTH(user_id) > 40 UNION ALL
SELECT count(user_id) as cnt FROM xxx_user_1 WHERE CHAR_LENGTH(user_id) > 40 UNION ALL
SELECT count(user_id) as cnt FROM xxx_user_2 WHERE CHAR_LENGTH(user_id) > 40 UNION ALL
SELECT count(user_id)as cnt FROM xxx_user_3 WHERE CHAR_LENGTH(user_id) > 40 UNION ALL
SELECT count(user_id) as cnt FROM xxx_user_4 WHERE CHAR_LENGTH(user_id) > 40 UNION ALL
SELECT count(DISTINCT(user_id)) as cnt FROM xxx_user_5 WHERE CHAR_LENGTH(user_id) > 40 UNION ALL
SELECT count(DISTINCT(user_id)) as cnt FROM xxx_user_6 WHERE CHAR_LENGTH(user_id) > 40 UNION ALL
SELECT count(DISTINCT(user_id)) as cnt FROM xxx_user_7 WHERE CHAR_LENGTH(user_id) > 40 UNION ALL
SELECT count(DISTINCT(user_id)) as cnt FROM xxx_user_8 WHERE CHAR_LENGTH(user_id) > 40 UNION ALL
SELECT count(DISTINCT(user_id)) as cnt FROM xxx_user_9 WHERE CHAR_LENGTH(user_id) > 40
)as countdata
注:union all 与 union的区别
效率上,union all比union更好一点。因为union在执行的时候会把结果集进行排序并删除重复的记录,而union all则会把两个结果集原封不动地合并在一起
delete 和 truncate 区别
delete 和 truncate都能删除表中数据,但是有以下几个不同点:
1.条件删除
delete可以带where执行条件删除,但是truncate不能;所以delete可以条件删除,而truncate就是清空表中多有数据2.事务
delete是数据操作语言DML,操作时原数据会被放到rollback segment中,可以被回滚;而truncate是数据定义语言DDL, 操作时不会进行存储,不能进行回滚3.速度
truncate > delete
delete语句是逻辑删除,及逐行删除数据,然后在事务日志中为所删除的每行记录一行;
而truncate是物理删除,直接清空物理文件,再重新创建表。
-
4.物理空间
从上面的提到的逻辑删除和物理删除可以看出来,truncate清空数据后,物理空间就直接释放了,但是delete不会, delete 进行删除操作的时候,只会将已经删除的数据标记为删除,并没有把数据文件删除,因此并不会彻底的释放空间。这些被删除的数据会被保存在一个链接清单中,当有新数据写入的时候,MySQL 会重新利用这些已删除的空间进行再写入。如果delete操作后,想要立即释放空间,可以执行optimize table table_name语句,OPTIMIZE TABLE 将重新组织表数据和相关索引数据的物理存储空间,减少存储空间并提高I/O访问效率。关于optimize 可见
Mysql表空间碎片释放
- 5.主键id
主键id通常都是自增的,从上面的提到的逻辑删除和物理删除可以看出来,delete删除数据后,id水位线并不会变更,而truncate相当于是重建表了,那id水位当然是再次从1开始了;