Java基础与应用场景介绍(二)

数据库
数据库的分类及常用的数据库

数据库分为:关系型数据库和非关系型数据库。
关系型:MySql、Oracle、SqlServer等。
非关系型:redis、memchache、mongodb、hadoop等。

数据库的三范式

范式就是规范,就是关系型数据库在设计表时,要遵循的三个规范。
想要满足二范式,必须先满足一范式,想要满足三范式,必须满足一范式。
第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。列数据不可分割。
第二范式(2NF)要求数据表中的每个行必须可以被唯一的区分。为了实现区分通常为表上加上一个列,一存储各个实例的唯一性。
第三范式(3NF)必须先满足第二范式(2NF)。第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。(外键)。

事务四个基本特征或ACID特性

事务是并发控制的单位,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。
例子:一个转账必须A账号扣钱成功,B账号加钱成功,才算真正的转账成功。
事务必须满足四大特征:原子性、一致性、隔离性、持久性/持续性。
原子性:表示事务内操作不可分割,要么都成功、要么都失败。
一致性:要么都成功,要么都失败,后面的失败对前面进行回滚。
隔离性:一个事务开始后,不能被后面其他事务所干扰。
持久性/持续性:表示事务开始,就不能终止。

MySQL数据库的默认最大连接数

特定的服务器上面数据库只能支持一定数目同时连接,这时候我们一般会设置最大连接数(最多同时服务器多少连接)。在数据库安装时都会有一个默认的最大连接数为100。我们可以通过查找my.ini来修改max_connection属性。

MySQL的分页、Order的分页

在数据很多时,一个页面显示不过来,所以需要进行分段显示,所以就会用到分页。
Mysql是使用关键字limit来进行分页的[limit offset, size],表示从多少索引去多少位。
Oracle,需要三层嵌套查询。
Mysql:String sql = “select * from students order by id limit " + pageSize*(pageNumber-1)+”,"+pageSize;
Oracle:String sql = "select * from " + (select , rownum rid from (select * from students order by postime desc) where rid <= " + pageSizepageNumber + “) as t” + "where t > " + pageSize*(pageNumber-1);

数据库的触发器使用场景

触发器需要有触发条件,当条件满足以后做什么操作。
触发器用处用处还是很多的,比如校内网、开心网、Fecebook,发表一个日志,自动通知好友,其实就是在增加日志时做了一个触发器,再向通知表中写入条目。因为触发器效率高。而UCH没有用触发器,效率和数据处理能力很低。
每插入一个帖子,都希望将面板中的最后发表时间、帖子总数字段进行同步更新,用触发器做效率就很高。

create table board1(id int primary key auto_increment, name varchar(50), articleCount int);
create table article1(id int primary key auto_increment, title varchar(50), bid int references board1(id));
delimiter |
create trigger insertArticle_Trigger after insert on article1 for each row begin
update board1 set articleCount=articleCount + 1 where id = NEW.bid;
end;

delimiter |

insert into board1 value(null, 'test', 0);
#结果
inset into article1 value(null, 'test', 1)
数据库存储过程

数据库存储过程具有如下优点:
1、存储过程只在创建时进行编译,以后每次执行存储过程都不需要重新编译,而一般SQL语句每执行一次就编译一次,因此使用存储过程可以大大提高数据库执行速度。
2、通常复杂的业务逻辑需要多条SQL语句,这些语句要分别从客户端发送到服务器,当客户机和服务器之间的操作很多时,将产生大量的网络传输。如果将这些操作放在一个存储过程中,那么客户机和服务器之间的网络传输就会大大减少,降低网络负载。
3、存储过程创建一次便可重复使用,从而可以减少数据库开发人员的工作量。
4、安全性高,存储过程可以屏蔽对底层数据库对象的直接访问,使用Execute权限调用存储过程,无需拥有访问底层数据库对象的显式权限。
简单存储过程实现

create procedure insert_Student(_name varchar(50), _age int, out_id int)
begin
    insert into student value(null, _name, _age);
    select max(stuId) into_id from student;
end;

#调用存储过程
call insert_Student('xipiker', 21, @id);
select @id;
JDBC理解

Java database connection java数据库连接,数据库管理系统(mysql oracle等),每个数据库管理系统支持的命令是不一样的。
Java只定义接口,让数据库厂商自己实现接口,对于我们开发者而言,只需要导入对应的厂商开发的实现即可。然后以接口的方式进行调用.

JDBC连接数据库的基本流程

流程:加载驱动程序、获取连接、设置参数、执行、释放连接。
加载驱动(com.mysql.jdbc.Driver、com.oracle.jdbc.driver.OracleDriver)。
获取连接(DriverManager.getConnection([url], [username], [password]))。
设置参数(Statement、PreparedStatement、[XXX].setXXX([index], value))。
执行(executeQuery、executeUpdate)。
释放连接(释放连接要从小到大,必须方法finnaly)。

实体类

public class Student {
    private String Id;
    private String Name;
    private String Sex;
    private String Age;
    ...
}

获取连接

//获取连接
private static Connection getConn() {
    String driver = "com.mysql.jdbc.Driver";
    String url = "jdbc:mysql://localhost:3306/samp_db";
    String username = "root";
    String password = "";
    Connection conn = null;
    try {
        Class.forName(driver); //classLoader,加载对应驱动
        conn = (Connection) DriverManager.getConnection(url, username, password);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return conn;
}

插入Insert

private static int insert(Student student) {
    Connection conn = getConn();
    int i = 0;
    String sql = "insert into students (Name,Sex,Age) values(?,?,?)";
    PreparedStatement pstmt;
    try {
        pstmt = (PreparedStatement) conn.prepareStatement(sql);
        pstmt.setString(1, student.getName());
        pstmt.setString(2, student.getSex());
        pstmt.setString(3, student.getAge());
        i = pstmt.executeUpdate();
        pstmt.close();
        conn.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return i;
}

更新Update

private static int update(Student student) {
    Connection conn = getConn();
    int i = 0;
    String sql = "update students set Age='" + student.getAge() + "' where Name='" + student.getName() + "'";
    PreparedStatement pstmt;
    try {
        pstmt = (PreparedStatement) conn.prepareStatement(sql);
        i = pstmt.executeUpdate();
        System.out.println("resutl: " + i);
        pstmt.close();
        conn.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return i;
}

查询Select

private static Integer getAll() {
    Connection conn = getConn();
    String sql = "select * from students";
    PreparedStatement pstmt;
    try {
        pstmt = (PreparedStatement)conn.prepareStatement(sql);
        ResultSet rs = pstmt.executeQuery();
        int col = rs.getMetaData().getColumnCount();
        System.out.println("============================");
        while (rs.next()) {
            for (int i = 1; i <= col; i++) {
                System.out.print(rs.getString(i) + "\t");
                if ((i == 2) && (rs.getString(i).length() < 8)) {
                    System.out.print("\t");
                }
             }
            System.out.println("");
        }
            System.out.println("============================");
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}

删除Delete

private static int delete(String name) {
    Connection conn = getConn();
    int i = 0;
    String sql = "delete from students where Name='" + name + "'";
    PreparedStatement pstmt;
    try {
        pstmt = (PreparedStatement) conn.prepareStatement(sql);
        i = pstmt.executeUpdate();
        System.out.println("resutl: " + i);
        pstmt.close();
        conn.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return i;
}

测试代码

public static void main(String args[]) {
    JDBCOperation.getAll();
    JDBCOperation.insert(new Student("Achilles", "Male", "14"));
    JDBCOperation.getAll();
    JDBCOperation.update(new Student("Bean", "", "7"));
    JDBCOperation.delete("Achilles");
    JDBCOperation.getAll();
}   
JDBC中PreparedStatement相比Statement的好处

好处:
1、PreparedStatement是预编译的,比Statement速度快。
2、代码的可读性和可维护性高。(虽然用PreparedStatement来代替Statement会使代码的多出几行,但是这样的代码可读性比较高)。
3、安全性。(PreparedStatement可以防止SQL注入攻击,而Statement却不能,有疑问可以参考上面的代码)。

数据库连接池的作用

1、限定数据库连接的个数,不会导致由于数据库连接过多导致系统运行缓慢或崩溃。
2、数据库连接不需要每次都进行创建或销毁,节约了资源。
3、数据库连接不需要每次都去创建,响应时间更快。

框架
概述

框架(Framework)是一个框子(指约束性),也是一个架子(指其支撑性)。
IT语境中的框架,指为解决一个开放性问题而设计的具有一定约束性的支撑结构。在此结构上可以根据具体扩展、安插更多的组成部分,从而迅速和方便地构建完整的解决问题的方案。

描述

1、框架本身一般不完整到可以解决特定问题,但是可以帮助您快速解决特定问题:没有框架所有的工作都从零开始做,有了框架,为我们提供了一定的功能,我们就可以在框架的基础上进行开发,极大解放了生产力。不同的框架是为了解决不同领域的问题而出现的,一定要为了解决问题去学习框架,和开发新的框架。
2、框架天生是为了扩展而设计的。
3、框架里面可以为后续扩展的组件提供更多辅助性、支持性的方便易用的实用工具(utillities),也就是说框架时常配套了一些帮助解决某类问题的库(libraries)或工具(tools)。java中的一系列jar包,基本就是对jdk功能的扩展。

MVC模式

MVC全名是Modle View Controller,是模型(Modle)、视图(View)、控制器(Controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时不需要重新编写业务逻辑。
最简单、最经典就是Jsp(View)+Servlet(Controller)+JavaBean(Model)。
流程:当控制器收到来自用户的请求,控制器调用JavaBean完成业务,完成业务后通过控制器跳转Jsp页面的方式给用户进行反馈信息,Jsp再给用户进行响应。

MVC框架

为解决传统MVC模式(Jsp+Servlet+JavaBean)的一些问题出现的框架。
问题描述:
1、所有的Servlet和Servlet映射都要配置在web.xml中,如果项目太大,web.xml就太庞大了,并且不能实现模块化管理。
2、Servlet的主要功能就是接收参数、调用逻辑、跳转页面,比如像其他字符编码、文件上传等功能也要写在Servlet中,不能让Servlet主要功能而需要做一些特例。
3、接收参数比较麻烦(String name = request.getParemeter(“name”);User user = new User();user.setName(name)?,不能通过model接收,只能单个接收,接收完成后转换封装model。
4、跳转页面方式比较单一(forword、redirect),并且当我的页面名称发生改变时需要修改Servlet源代码。

Spring MVC的执行流程

1、用户向服务器发生请求,请求被Spring前端控制Servlet DispatcherServlet捕获。(捕获请求)。
2、DispatcherServlet对该请求进行解析,得到请求资源标识符(URI),然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截),最后以HandlerExecutionChain对象的形式返回。(查找Handler)。
3、DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter,提取Request中模型数据,填空Handler入参,开始执行Handler(Controller),Handler执行完成后,向DispatcherServlet返回一个ModelAndView对象(执行Handler)。
4、DispatcherServlet根据返回的ModelAndView,选择一个合适的ViewResolver(必须是已注册到Spring容器中的ViewResolver)。(选择ViewResolver)。
5、通过ViewResolver结合Model和View,来渲染视图,DispatcherServlet将渲染结果返回给客户端。(渲染返回)。
流程:核心控制器捕获请求、查询Handler、执行Handler、选择ViewResolver、通过ViewResolver渲染视图并通过DispatcherServlet进行返回。

Spring MVC 和 Struts2的不同

1、核心控制器(前端控制器、预处理控制器):对于使用过mvc框架的人来说这个词应该不会陌生,核心控制器的主要用途是处理所有的请求,然后对那些特殊的请求(控制器)统一进行处理(字符编码、文件上传、参数接收、异常处理等),SpringMVC核心控制器是Servlet,而Struts3是Filter。
2、控制器实例:SpringMVC会比Struts2快一些(理论上说),SpringMVC是基于方法设计,而Struts2是基于对象,每次发一次请求都会实例一个action,每个action都会被注入属性,而Spring更像Servlet一样,只有一个实例,每次请求执行对应的方法即可(注意:由于是单例实例,所以应当避免全局变量的修改,这样会产生线程安全问题)。
3、管理方式:大部分的公司的核心架构中,就会使用到Spring,而SpringMVC又是Spring中的一个模块,所以Spring对于SpringMVC的控制器管理更加简单方便,而且提供了全注解方式进行管理,各种功能的注解都比较全面,使用简单,而Strust2需要采用XML很多的配置参数来管理(虽然也可以采用注解,但是几乎没有公司那样使用)。
4、参数传递:Struts2自身提供多种参数接收,其实都是通过(ValueStack)进行传递和赋值,而SpringMVC是通过方法的参数传递进行接收。
5、学习难度:Spring比较简单。
6、Intercepter的实现机制:Struts有以自己的intercepter机制,SpringMVC用的是独立的AOP方式。
7、SpringMVC处理Ajax请求,直接返回数据,方法中使用注解@ResponseBody,SpringMVC自动帮我们将对象转为JSON数据。而Struts是通过插件的方式进行处理。

Spring两大核心

Spring是J2EE应用程序框架,是轻量级的IOC和AOP的容器框架(相对重量级的EJB而言),主要是针对JavaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,ibatis框架进行组合。
1、IOC(Inversion of Control)或DI(Dependency Injection)
IOC控制权反转
原来:我们的Service需要调用Dao,Service就需要创建Dao。
Spring:Spring发现你的Service依赖于Dao,就直接给你进行注入。
2、AOP(面向切面编程)
核心原理:使用动态代理设计模式的方式在执行前后或出现异常做后相关逻辑,我们主要使用AOP来做事务处理、权限判断、日志…

AOP是什么

AOP(面向切面编程)
核心原理:使用动态代理设计模式的方式在执行前后或出现异常做后相关逻辑,我们主要使用AOP来做事务处理、权限判断、日志…
1、事务处理:执行方法前,开启事务、执行完毕后关闭事务、出现异常后回滚事务。
2、权限判断:在执行方法前,判断是否具有权限。
3、日志:在执行方法前进行日志处理。
4、…

ORM是什么

对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系型数据库存在的不匹配的现象技术。简单的说,ORM是通过描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。那么到底如何实现持久化?一种简单的方案是采用硬编码方式(Jdbc操作Sql方式),为每一种可能的数据库访问操作提供单独的方法。
这种方式存在的缺陷:
1、持久化层缺乏弹性,一旦出现业务需求的变更,就必须修改持久化层的接口。
2、持久化层同时与域模型与关系数据库模型绑定,不管域模型还是关系数据库模型发生变化,都要修改持久化层的相关代码,增加了软件的维护难度。
ORM提供了实现持久化层的另一种模式,它采用映射元数据来描述对象关系映射,使得ORM中间件能在任何一个应用的业务逻辑层和数据库层之间充当桥梁。Java典型的ORM框架有:Hibernate、iBatis(MyBatis)、SpeedFramework。
ORM的方法基于三个核心的原则:
1、简单:以最基本的形式建模数据。
2、传达性:数据结构被任何人都能理解的语言文档化。
3、准确性:基于数据模型创建正确标准化了的结构。
总结:对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系型数据库存在的不匹配的现象技术。可以简单的方案是采用硬编码方式(Jdbc操作Sql方式),为每一种可能的数据库访问操作提供单独的方法。这种方法存在很多缺陷,可以使用ORM框架(为了解决面向对象与关系型数据库存在的不匹配的现象技术)来解决如此缺陷。

iBatis(MyBatis)与Hibernate有什么不同?

相同点:都是Java中的ORM框架、屏蔽Jdbc Api的底层访问细节,使用我们不用与Jdbc Api打交道,就可以完成对数据库的持久化操作,Jdbc Api编程流程固定,还将Sql语句和Java代码混淆在一起,经常需要拼凑Sql语句,细节繁琐。
iBatis的好处:屏蔽Jdbc Api的底层访问细节,将Sql语句与Java代码进行分离;提供了将结果集自动封装称为实体对象和对象的集合的功能queryForList返回对象集合,用queryForObject返回单个对象;提供了自动将实体对象的属性传递给Sql语句的参数。
Hibernate的好处:Hibernate是一个全自动的ORM映射工具,它可以自动生成Sql语句,并执行并返回Java结果。
不同点:
1、Hibernate要不iBatis功能要强大很多,因为Hibernate自动生成Sql语句。
2、iBatis需要我们自己在xml配置文件中写Sql语句,Hiberanate可以很好帮我们完成,但是对于特别复杂的查询,Hibernate就很难适应了,这时候用iBatis就是不错的选择,因为iBatis还是由我们自己写Sql语句。
3、iBatis要比Hibernate简单很多,iBatis是面向Sql的,不用考虑对象间一些复杂的映射关系。

Hibernate映射对象的状态

临时状态/瞬时状态(Transient):刚刚用new语法创建,没有被持久化,不处于session中(没有使用session的方法去操作临时对象),该对象称为临时对象。
持久化状态/托管状态(Persistent):已经被持久化,加入到session的缓存中。session是没有关闭该状态对象为持久化对象。
游离状态/托管状态(datached):已经被持久化,但不处于session中。该状态的对象为游离对象。
删除状态(removed):对象没有关联的Id,并且在session管理下,但是已经被计划(事务提交的时候,commit())删除。如果没有事务就不能删除。
以上几种映像对象的状态可以互相转换。

Hibernate的缓存

一、为什么要用Hibernate缓存
Hibernate是一个持久层框架,经常访问物理数据库。为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。为了提供访问速度,把磁盘或数据库访问变成内存访问。
二、Hibernate缓存原理是怎样的?Hibernate缓存包括两大类:一级缓存和二级缓存。
1、Hibernate一级缓存又称为"Session的缓存"。
Session缓存内置不能被卸载,Session的缓存是事务范围的缓存(Session对象的生命周期通常对应一个数据库事务或者一个应用程序)。一级缓存中,持久化类的每个实例都具有唯一的OID。
2、Hibernate二级缓存又称为"SessionFactory的缓存"。由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。二级缓存时可选的,是一个可配置的插件,默认下SessionFactory不会启用这个插件。Hibernate提供了org.hibernate.cache.CacheProvider接口,它充当缓存插件与Hibernate之间的适配器。
总结:Hibernate中的缓存分为一级缓存和二级缓存。一级缓存就是Session级别的缓存,在事务范围内有效是内置的不能被卸载,二级缓存是SessionFactory级别的缓存,从应用启动到应用介绍有效果,是可选的,默认没有二级缓存,需要手动开启。
什么样的数据适合二级缓存呢?
1、很少被修改的数据。
2、经常被查询的数据。
3、不是很重要的数据,允许出现偶尔并发的数据。
4、不会被并发访问的数据。
5、常量数据。
扩展:Hibernate的二级缓存默认是不支持分布式缓存的。使用memcache、redis等中央缓存来代替二级缓存。

WebService使用场景

WebService是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于Http协议的网络应用间的交互。
1、异构系统(不同语言)的整合。
2、不同客户端的整合:浏览器、手机端(Android、IOS、塞班)、微信端、Pc端等终端的访问。
3、例子:天气预报(可以通过实现webservice客户端调用远程天气服务实现)、单点登录(一个服务是所有系统的登录)。

Activiti
概述

Activiti是一个业务流程管理(BPM)和工作流系统,适用于开发人员和系统管理员,其核心是超快速、稳定的BPMN2流程引擎。它易于Spring集成使用。主要在OA,把线下流程放到线上。把现实生活中的一些流程固话定义到系统中,然后通过输入表单数据完成业务。
使用场景:
1、OA系统-请假流程,小于三天的,一级管理审批,大于三天的二级管理审批。
2、OA系统-报销流程,1000、2000、3000…

数据库优化
优化流程

定位:查找、定位慢查询。
优化手段:
1、创建索引:创建适合的索引,我们就可以现在索引中查询,查询到以后直接找到对应的记录。
2、分表:当一张表的数据比较多或者一张表的某些字段的值比较多并且很少使用时,采用水平分表和垂直分表来优化。
3、读写分离:当一台服务器不能满足需求时,采用读写分离的方式进行集群。
4、缓存:使用缓存redis进行缓存。
5、一些常用的Sql优化。

查找并定位慢查询?

在项目自验项目转测试之前,在启动MySql数据库是开始慢查询,并且把执行慢的语句写到日志中,在运行一定时间后。通过查看日志找到慢查询语句。(这一块学习一下,怎么把慢查询打印到日志管理系统中)。

数据库三范式

范式就是规范,就是关系型数据库在设计表时,要遵循的三个规范。
想要满足二范式,必须先满足一范式,想要满足三范式,必须满足一范式。
第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。列数据不可分割。
第二范式(2NF)要求数据表中的每个行必须可以被唯一的区分。为了实现区分通常为表上加上一个列,一存储各个实例的唯一性。
第三范式(3NF)必须先满足第二范式(2NF)。第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。(外键)。

选择合适的存储引擎

在开发中,我们经常使用的存储引擎是myISAM、InnoDB、Memory。
MyISAM存储引擎:如果表对事务的要求不高,同时是以查询和添加为主的,我们考虑使用MyISAM存储引擎,比如BBS中的发帖表、回复表。
InnoDB存储引擎:对事务要求高,保存的数据都是重要数据,我们建议使用InnoDB,比如订单表、账号表。
Memory存储引擎:我们数据变化频繁,不需要入库,同时又频繁的查询和修改,我们考虑使用Memory,速度极快。
MyISAM和InnoDB主要区别:
1、事务安全:MyISAM不支持、InnoDB支持。
2、查询和添加速度:MyISAM不支持事务就不用考虑同步锁,查找和添加的速度快。
3、支持全文索引:MyISAM支出、InnoDB不支持。
4、锁机制:MyISAM支持表锁,而InnoDB支持行锁。
5、外键MyISAM不支持外键,InnoDB支持外键(通常情况下是不设置外键,一般都是在程序中保证数据的一致性)。

创建合适的索引

缩影(Index)是帮助DBMS高效获得数据的结构。
分类:普通索引、唯一索引、主键索引、全文索引。
普通索引:运行重复的值出现。
唯一索引:除了不能有重复的记录外,其它和普通索引一样。
主键索引:是随着设定主键而创建的,也就是把某个列设为主键的时候,数据库就会给列创建索引,这就是主键索引,唯一且没有null。
全文索引:用来对表中的文本域(char、varchar、text)进行索引,全文索引针对MyISAM,例子([explain select * from articles where match(title, body) against(‘database’);])。

索引使用技巧

索引弊端:
1、占用磁盘空间。
2、对dml(插入、修改、删除)操作有影响,变慢。
使用场景:
1、在where条件经常使用,如果不做查询就没有意义了。
2、该字段的内容不是唯一的几个值(sex)。
3、字段内容不是频繁化。
具体技巧:
1、对于创建索引(符合索引),不是使用的第一部分就不会使用索引。
alter table dept add index my_ind (dname, loc);//dname左边的列,loc右边的列。
explain select * from dept where dname = ‘aaa’;//会用到索引。
explain select * from dept where loc = ‘aaa’;//不会使用到索引。
2、对于使用like的查询,查询如果是’%aaa’不会使用到索引而’aaa%'会用到索引。所以在like查询时,'关键字’的最前面不能使用”%“或者”_“这样的字符,如果一定要前面有变化值,则考虑使用全文索引->sphinx。
3、如果条件中有or,有条件没有使用索引,即使其中有条件带索引也不会使用,换言之,就是要求使用的所有字段,都必须单独使用是能使用索引。
4、如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引。
explain select * from dept where dname = ‘111’;
explain select * from dept where dname = 111;(数值字段转换为字符串)
explain select * from dept where dname = qqq;(报错)
也就是说,如果列是字符串类型,无论是不是字符串一定要用引号把它包括起来。
5、如果mysql估计使用全表扫描要比使用索引快,则不使用索引。比如表中只有一条记录。

分表

分表分为水平(按行)分表和垂直(按列)分表。
经验:MySql数据库一般达到百万级别,查询效率会很低,容易造成表锁,甚至堆积很多连接,直接挂掉,水平分表能够很大程度减少这些压力。
水平分表:
如果一张表中某个字段值非常多(长文本、二进制等),而且只有在很少的情况下会查询,这时候就可以把字段多个单独放到一个表,通过外键关联起来。比如考试详情,一般我们只关注分数,不关注详情。
水平分表策略:
1、按时间分表:这种分表方式有一定局限性,当数据有较强的实效性,如微博发送记录、微信消息记录等,这种数据很少有用户会查询几个月前的数据,如就可以按月分表。
2、按时间区范围分表:一般在有严格的自增id需求上,如按照user_id水平分表(table1 user_id 从1~100w;table2 user_id 从101~200w;table3 user_id 从201~300w)。
3、hash分表:通过一个原始目标的ID或者名称通过一定的hash算法算出数据存储表的表名,然后访问相应的表。

读写分离

一台数据库支持的最大并发连接数是有限的,如果用户并发访问太多,一台服务器满足不了要求就可以集群处理。MySql的集群处理技术最常用的就是读写分离。
主从同步:
数据库最终会发数据持久化到磁盘,如果集群必须确保每个数据库服务器的数据是一致的,能改变数据库数据的操作都往主数据库去写,而其他的数据库从主数据库上同步数据。
读写分离:
使用负载均衡来实现写的操作都往主数据库服务器去,而读的操作往从数据库服务器去。

缓存

在持久层(dao)和数据库(db)之间添加一个缓存层,如果用户访问的数据已经缓存起来时,在用户访问时直接从缓存中获取,不用访问数据库。而缓存是操作内存级,访问速度快。作用是减少数据库服务器的压力,减少访问时间。
Java中常用的缓存有:
1、Hibernate的二级缓存、该缓存不能完成分布式缓存。
2、可以使用Redis、Memcache等作为中央缓存,对缓存的数据进行处理。

语句优化

DDL优化:
1、通过禁用索引来提供导入数据性能。这个操作主要针对有数据的表,追加数据。

#除去数据
alter table test3 DISABLE keys;
#批量插入数据
insert into test3 select * from test;
#恢复键
alter table test3 ENABLE keys;

2、关闭唯一效验:

#关闭
set unique_checks = 0;
#开启
set unique_checks = 1;

3、修改事务提交方式(导入)(变多次提交为一次):

#关闭
set autocommit = 0;
#批量插入
#开启
set autocommit = 1;

DML优化(变多次提交为一次):

insert into test value(1,2);
insert into test value(1,3);
insert into test value(1,4);
#合并为一条
insert into test values(1,2),(1,3)(1,4);

DQL优化:
Order by 优化:
1、多用索引排序。
2、普通结果排序(非索引排序)Filesort。
Group by 优化:
使用order by null,取消默认排序。
子查询优化:
在客户列表找到不在支付列表的客户。

#在客户列表找到不在"支付列表"的客户,查询没买过东西的客户。
explain
select * from customer where customer_id not in (select DISTINCT customer_id from payment);#子查询、这是基于func外键

explain
select * from customer c left join patment p on(c.customer_id=p.customenr_id) where p.customer_id is null;#这是基于"索引"外键

Or 优化:
在两个独立索引上使用or:
1、or两边都是用索引字段做判断,性能好。
2、or两边,有一边不用,新年差。
3、如果employee表的name和email这两列是一个复合索引,但是如果是:name=‘A’ or email='B’这种方式,不会用到索引。
Limit 优化:

select film_id,desription from film order by title limit 50,5;
select a.film_id,a.desription from film a inner in join (select film_id from film order by title limit 50,5)b on a.film_id = b.film_id
jdbc批量插入几百万条数据

方法:
1、变多次为一次(value change to values)。
2、使用批量操作
可参考博文批量插入详解

Redis
概述

Redis是一个key-value的nosql数据库,先存到内存中,会根据一定的策略持久化到磁盘,即使断电也不会丢失数据,支持的数据类型比较多。主要来做缓存数据库的数据和web集群是当做中央缓存存放session。

Redis使用场景

缓存:把经常需要查询的、很少修改的数据,放到读速度很快的空间(内存),以便下次访问减少时间,减轻压力,减少访问时间。
计数器:Redis中的计数器是原子性的内存操作。可以解决库存溢出问题、进销存系统溢出问题。
session缓存服务器:web集群时作为session缓存服务器。
缓存队列等。

Redis对象保存方式

Json字符串:需要对象转为Json字符串,当做字符串处理,直接使用get、set来设置或获取。
1、优点:设置和获取比较简单。
2、缺点:没有提供专门的方法,需要把对象转为Json。
字节:需要做序列化,就是把对象转为字节流来保存。
如果担心Json转对象会消耗资源的情况,这个问题需要考量几个地方。
第一点:就是使用Json转Lib是否会存在性能问题。
第二点:就是数据的数据量级别,如果是存储百万级的大数据对象,建议采用存储序列化对象方式。如果是少量的数据级对象,或者是数据对象字段不多,还是建议采用Json转换为String方式。
毕竟Redis对象存储字符类型这部分优化非常好,具体采用的方式与方法,主要看自己的使用的场景。

Redis数据淘汰机制

在Redis中,允许用户设置最大使用内存大小Server-maxmemory,在内存限定的情况下是有用的,例如,在一台8G机子上部署了4个Redis服务点,每个服务器分配1.5G的内存大小,减少内存紧张的情况,由此获取更多为稳健的服务。
内存大小有限,需要保存有效数据。Redis内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。
Redis提供6种数据淘汰策略:
1、volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰。
2、volatile-ttl:从设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰。
3、valatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰。
4、allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰。
5、allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰。
6、no-enviction(驱逐):禁止驱逐数据。

Java访问Redis

1、使用Jedis Java客户端来访问Redis服务器,有点类似通过JDBC方式访问MySql一样。
2、当然如果是使用Spring进行集成时,可以使用Spring Data来访问Redis,Spring Data是对Jedis的二次封装,jdbcTemplate、jdbc关系一样。

Redis集群

当一台数据无法满足要求,可以使用Redis集群来处理类似于Mysql读写分离。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值