数据库总结

数据库总结

一.Centos安装Mysql

1.下载mysql包。地址:https://dev.mysql.com/downloads/mysql/

进去选择配置如下:

选择

 

 

2.在centos下随便一个目录下进行解压。

tar -vxf  MySQL-5.6.44-1.el7.x86_64.rpm-bundle.tar

执行命令

groupadd  mysql

useradd -g mysql -m mysql

rpm -e mariadb-libs-1:5.5.60-1.el7_5.x86_64

rpm -ivh MySQL-server-5.6.44-1.el7.x86_64.rpm

rpm -ivh MySQL-client-5.6.44-1.el7.x86_64.rpm

rpm -ivh MySQL-devel-5.6.44-1.el7.x86_64.rpm

rpm -ivh MySQL-shared-5.6.44-1.el7.x86_64.rpm

 chown -R mysql:mysql /var/lib/mysql

/etc/init.d/mysql start

3.上述安装过程中,有任何报错直接百度。接下来进行密码更改。

随机密码在/root/.mysql_secret  里,第一次登录需要用到里面的密码。

mysql -uroot -p

4.更改密码。

直接执行set PASSWORD=password('root');

设置远程连接 grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option;

 FLUSH PRIVILEGES;

5.tip:安装报错小提示。

出现mariadb错误时,直接卸载mariadb版本,然后再装mysql。查询mariadb:

rpm -qa | grep mariadb   然后卸载 rpm -e maraidb*****

出现perl(Data::Dumper) 被 MySQL-server-5.6.44-1.el7.x86_64 需要  错误时,安装如下

yum install -y perl perl-devel

yum -y install autoconf

yum install -y perl-Data-Dumper

然后再重新安装Mysql即可

如果有类似‘依赖检测失败: mariadb-libs 被 mysql-community-libs-8.0.23-1.el7.x86_64 取代’错误

执行yum remove mysql-libs

二、Mysql语句练习

近期突然有事情要加强sql练习,本文是在转载的基础上自己进行尝试练习
原文地址:
https://blog.csdn.net/fashion2014/article/details/78826299

CREATE TABLE `Student`(
`s_id` VARCHAR(20),
`s_name` VARCHAR(20) NOT NULL DEFAULT '',
`s_birth` VARCHAR(20) NOT NULL DEFAULT '',
`s_sex` VARCHAR(10) NOT NULL DEFAULT '',
PRIMARY KEY(`s_id`)
);

CREATE TABLE `Course`(
`c_id` VARCHAR(20),
`c_name` VARCHAR(20) NOT NULL DEFAULT '',
`t_id` VARCHAR(20) NOT NULL,
PRIMARY KEY(`c_id`)
);

CREATE TABLE `Teacher`(
`t_id` VARCHAR(20),
`t_name` VARCHAR(20) NOT NULL DEFAULT '',
PRIMARY KEY(`t_id`)
);

CREATE TABLE `Score`(
`s_id` VARCHAR(20),
`c_id` VARCHAR(20),
`s_score` INT(3),
PRIMARY KEY(`s_id`,`c_id`)
);

insert into Student values('01' , '赵雷' , '1990-01-01' , '');
insert into Student values('02' , '钱电' , '1990-12-21' , '');
insert into Student values('03' , '孙风' , '1990-05-20' , '');
insert into Student values('04' , '李云' , '1990-08-06' , '');
insert into Student values('05' , '周梅' , '1991-12-01' , '');
insert into Student values('06' , '吴兰' , '1992-03-01' , '');
insert into Student values('07' , '郑竹' , '1989-07-01' , '');
insert into Student values('08' , '王菊' , '1990-01-20' , '');

insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');

insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');

insert into Score values('01' , '01' , 80);
insert into Score values('01' , '02' , 90);
insert into Score values('01' , '03' , 99);
insert into Score values('02' , '01' , 70);
insert into Score values('02' , '02' , 60);
insert into Score values('02' , '03' , 80);
insert into Score values('03' , '01' , 80);
insert into Score values('03' , '02' , 80);
insert into Score values('03' , '03' , 80);
insert into Score values('04' , '01' , 50);
insert into Score values('04' , '02' , 30);
insert into Score values('04' , '03' , 20);
insert into Score values('05' , '01' , 76);
insert into Score values('05' , '02' , 87);
insert into Score values('06' , '01' , 31);
insert into Score values('06' , '03' , 34);
insert into Score values('07' , '02' , 89);
insert into Score values('07' , '03' , 98);

SQL join 用于根据两个或多个表中的列之间的关系,从这些表中查询数据。
JOIN: 如果表中有至少一个匹配,则返回行!!!!!
LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行!!!!!
RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行!!!!
FULL JOIN: 只要其中一个表中存在匹配,就返回行!!!!!!!

1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数
自己的答案
SELECT s.*,a.s_score as a,b.s_score as b from student s
JOIN score a on a.s_id=s.s_id and a.c_id='01'
JOIN score b on b.s_id=s.s_id and b.c_id='02'
where a.s_score > b.s_score
原文答案
select a.* ,b.s_score as 01_score,c.s_score as 02_score from 
student a 
join score b on a.s_id=b.s_id and b.c_id='01'
left join score c on a.s_id=c.s_id and c.c_id='02' or c.c_id = NULL where b.s_score>c.s_score

2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数
和第一题相差不多,就不写了
这是原文答案
select a.* ,b.s_score as 01_score,c.s_score as 02_score from 
student a left join score b on a.s_id=b.s_id and b.c_id='01' or b.c_id=NULL 
join score c on a.s_id=c.s_id and c.c_id='02' where b.s_score<c.s_score

3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
select s.*,ROUND(AVG(a.s_score),2) as avg_score from 
student s
join score a on s.s_id = a.s_id
GROUP BY s.s_id HAVING avg_score >=60;

5、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩
select a.s_id,a.s_name,count(b.c_id) as sum_course,sum(b.s_score) as sum_score from 
student a 
left join score b on a.s_id=b.s_id
GROUP BY a.s_id,a.s_name;
这里说一下left join,此处即便该学生没有分数,也会返回学生信息。而join只会返回匹配的行,而right join只会返回有成绩的学生信息。

6、查询"李"姓老师的数量
SELECT t.*,COUNT(t.t_id) from teacher t
where t.t_name LIKE '李%';

7、查询学过"张三"老师授课的同学的信息
SELECT s.*,t.t_name from student s
LEFT JOIN score sc on sc.s_id=s.s_id
LEFT JOIN course c on sc.c_id=c.c_id
LEFT join teacher t on c.t_id=t.t_id
where t.t_name='张三';
第二种方式:
select t.t_name,s.* from student s,score sc,course c,teacher t where t.t_id=c.t_id and sc.c_id=c.c_id and t.t_name='张三' and sc.s_id=s.s_id;
原文答案:
select a.* from 
student a 
join score b on a.s_id=b.s_id where b.c_id in(
select c_id from course where t_id =(
select t_id from teacher where t_name = '张三'));

8、查询没学过"张三"老师授课的同学的信息
select s.* from student s where s.s_id not in(select sc.s_id from score sc,course c,teacher t where t.t_id=c.t_id and sc.c_id=c.c_id and t.t_name='张三');
思路为:找到所有学过张三老师的学生id,然后从所有学生里找不在这些id里的学生,即为没学过张三的学生。

三、有关Mybatis的知识点

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。

1.Mybatis一级缓存:之所以有缓存,主要是为了减少数据库的访问,如果在缓存命中,直接返回即可。所以当即增删改操作时会清空缓存,避免脏读。

一级缓存是SqlSession级别的,在springboot框架中每次访问controller都会生成一个sqlsession,并且使用完后都会执行close方法。

2.Mybatis二级缓存。二级缓存比一级缓存的作用范围大,即所有SqlSession都可以用,属于Mapper级别的(在同一个namespace下的mapper文件中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;第二次直接从缓存中取。当执行SQL时两次查询中间发生了增删改操作,则二级缓存清空。)。二级缓存默认关闭,需要在Mybatis配置中设置。

二级缓存是建立在同一个namespace下的,每个mapper都有自己的二级缓存,如果对表的操作查询可能有多个namespace时,由于namespaceA执行了增删改,并不会通知namespaceB,数据就是错的。

3.Mybatis执行sql语句:映射的spacename + "." + 标签的id。

4.sqlsession,定义了数据库的操作方法,包括selectOne,selectList,commit等。并且非线程安全。

mybatis通过动态代理,获取dao层的全限定名、方法名(即id),然后调用对应的mapper文件中的方法,对应SqlSession.getMapper(xxx.class)。

5.#和$都是传入参数的标识。#号对应占位符prepareStatement,执行效率更高,防止注入。是替换列值

$是连接sql语句和传入参数,是连接语句,如"select * from xxx where id=" + "1111",有注入风险,一般用于表名、列名的传入。

6.mybatis使用时需要提供实体类的无参构造方法,因为mybatis是执行sql语句查询时,通过无参构造函数创建对象,然后set同属性名的值。

 四、数据库小结

1.事务:是数据库操作的最小单元,是一个工作单元的一系列操作,这些操作作为一个整体,要么全执行,要么全不执行。

(1).A(原子性):即本次执行的系列操作要么全部成功要么全部失败。

(2).C(一致性):保证在一个事务中的多次操作的数据中间状态对其他事务不可见的,即只能看到结果值。还有就是执行前后数据要一致,比如A的100元转给B,其总额不变。

(3).I(隔离性):多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

(4).D(持久性):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,即使数据库发生故障也不应该对其有任何影响。

2.索引

聚集索引(主键索引):在数据库里面,所有行数都会按照主键索引进行排序。

非聚集索引:就是给普通字段加上索引。

联合索引:就是好几个字段组成的索引,称为联合索引。联合索引遵从最左前缀原则,比如创建索引时顺序是'name','age',则查询时也需要从name开始查询,即查询的时候查询条件精确匹配索引的左边连续一列或几列。

普通索引:CREATE INDEX 索引名 ON 表名(列名);

唯一索引:CREATE UNIQUE INDEX 索引名 ON 表名(列名) ;

不走索引的:

(1).Like这种就是%在前面的不走索引,在后面的走索引。

(2).用索引列进行计算的,不走索引。

(3).对索引列用函数了,不走索引。

(4).索引列用了!= 不走索引。

3.分库分表后ID的设置

分库分表就俩原因,要不就是单库并发太高,要不就是单库数据量太大。分完之后每个表都有自己的主键,这肯定不行,所以需要全局ID。

(1).可以设置不同的sequence,每个序列开始值不同(比如A服务器从1开始16位,B服务器从2开始16位...),就是扩展服务器到一定数目就有点难搞了。

(2).UUID,这个不用说,就是有序性基本没有了,而且32位属实有点长。

(3).通过redis获取序列。依赖于redis,也蛮不错的。

(4).通过已知的各种算法,比如snowflake。是把一个 64 位的 long 型的 id,1个bit 是不用的(1负数0正数),用其中的 41 bit 作为毫秒数,用10bit作为工作机器 id,12bit作为序列号。

五、三范式

一般都指的是关系型数据库的规范。

一范式:建表时保证列的原子性,即不可分割。比如有一列phone,既可以是座机,又可以是手机,应该分成两列。

二范式:在一范式的基础上,保证表的唯一性。即一张表只表示一种事物,每列和主键有依赖关系。

三范式:在二范式基础上,没有其他表中已有的除主键外的其他列,即没有传递性。

 六、MySql

1.常用的MySql数据类型有:

int或integer:大整数。

bigint:极大整数。

float:单精度浮点型。

double:双精度浮点型。

date/time/datetime:年月日/时分秒/年月日时分秒混合时间。

char:定长字符串。

varchar:变长字符串。

text:长文本数据。

char和varchar的n表示字符个数,char会进行超出截取、不满位数时补齐为空的特点,最大255。而varchar按照实际大小存储(不能超出指定n),最大65532。

七、 一次sql优化的心酸

有一个业务需求,从excel导入数据,最多2000条,每条需要查询A表一次、B表一次、C表一次,共6000次。其中A表40万数据,B表20万数据,C表4万数据,因为业务需求没办法一次关联全部查出,必须一条一条的查。数据库是pg。

最初业务人员没说这么多数据,突然一天数据量增到这么多,导致查询非常非常慢,甚至到了7分钟处理完业务,我真的不知道为什么,pg查询一次数据这么慢。

没办法只好慢慢磨。我的方法是,先查出三个表条数,循环利用分页从A、B、C三表查出数据,然后封装到hashmap里,这样减少数据库查询并减少内存里匹配次数。并且将外层循环list转换为iterator,每匹配到一次,就remove,减少循环次数。利用这几步操作,目前时间控制在30秒内,目前满足需求。等后续再次优化。。

posted @ 2019-07-23 18:25  chxLonely  阅读(455)  评论(0编辑  收藏  举报