在进行程序编写以及程序运行时,往往需要进行大量的数据库操作,但是,随着数据量的增大,数据字段的增多,在进行sql查询时往往可能消耗大量的时间,并且获取数据后还需要将数据发送给用户,这样就造成了程序响应时间过长,为了提高客户体验,数据库优化就必须进行(提高效率)
数据库优化提高效率大致分为三类:
1、硬件优化
提高数据库软件服务器硬件性能
2、软件优化
通过配置conf下my.ini进行属性的配置进行优化
3、sql语句优化
(1)尽量少进行计算
Mysql的作用是用来存取数据的,不是做计算的,做计算的话可以用其他方法去实现,mysql做计算是很耗资源的。
因为进行多表连接查询时,是由数据库内部根据查询的表与连接条件进行虚拟表的生成,由数据库内部进行处理过生成虚拟表数据之后再进行查询功能
(3)尽量减少或使用其他方式替代排序
排序操作会消耗较多的 CPU 资源。
对于MySQL来说,减少排序有多种办法,比如:
通过利用索引来排序的方式进行优化
减少参与排序的记录条数
非必要不对数据进行排序
(4)尽量使用查询的字段替换*
在进行查询时如果仅需要某一字段,最好使用字段直接查询,而不是*,如果使用* 会返回所有所有列返回了冗余数据,但是如果需求要求返回的就是所有列使用所有与直接书写字段是一样的
(5)尽量用 join 代替子查询
在进行子查询时。mysql会先执行子查询中sql语句返回结果之后再执行全部语句返回结果,会执行多次(数据库会为每次sql执行分配单独的资源),进行连接查询,查询与准备连接数据使用的是同一资源
(6)使用连接查询时尽量不要使用全连接
内连接与外连接进行数据连接时,是程序内部根据连接条件筛选连接返回数据,全连接是直接将所有数据直接返回,需要我们自己通过where进行条件筛选,
union 连接多条语句结果(上下连接)
(8)尽量用 union all 代替 union
union 和 union all 的差异主要是前者需要将两个(或者多个)结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的 CPU 运算,加大资源消耗及延迟。所以当我们可以确认不可能出现重复结果集或者不在乎重复结果集的时候,尽量使用 union all 而不是 union。
(9)尽量在连接时进行条件过滤
where进行过滤是在准备好数据之后进行条件过滤,如果在准备数据阶段已经将数据过滤结束,那么在进行数据查询时准备的数据就是我需要的数据就不需要再进行过滤.
(10)避免数据库的自动类型转换
进行数据操作时,通常使用where语句对条件字段进行判断或者直接使用字符串进行数据添加,数据库会对这些数据进行自动转换为指定字段的类型,只有转换不了时才会报错,但是这种转换及耗内存,所以在进行sql语句的书写时,对于字段数据类型进行额外书写(填写与数据库存储字段相同的数据类型),并且会导致索引失效
(11)对同一系统中不同sql先优化常用的而不是执行时间长的
对于破坏性来说,高并发的 SQL 总是会比低频率的来得大,因为高并发的 SQL 一旦出现问题,甚至不会给我们任何喘息的机会就会将系统压跨。而对于一些虽然需要消耗大量 IO 而且响应很慢的 SQL,由于频率低,即使遇到,最多就是让整个系统响应慢一点,但至少可能撑一会儿,让我们有缓冲的机会
(12)添加索引并进行全局优化
在进行sql优化时不能仅只针对于sql进行优化,还要考虑运行系统,与实际的需求,并注意,在进行优化时是否破破坏了索引。
(13)表、数据结构的优化
1、尽量不要使用null
2、Null会使索引维护复杂,推荐索引列使用not null
3、查询结果出错,not in !=查询结果在null下 总是空
4、需要额外判断是否为null
5、与该列其他值数据类型不匹配出错
6、优化字段结构(一定在初期建表时优化)
参考数据库三范式
主键唯一性:每一行数据一定拥有一个唯一主键,可以通过这个主键快速获取当前行数据
主键关联性:每一行数据的每一列都与主键存在关联
非主键列非关联性:每一行每一列除与主键存在关联以为与其他列不存在关联(每列不可再分)
索引
索引是提高sql查询效率最常用的方式之一,可以理解为为指定字段创建目录,在使用查询时通过where对这个字段进行查询时,会先去目录进行查询之后进行操作
创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
建立索引会占用磁盘空间的索引文件。
Mysql中索引类型一共分为4种
1主键索引 primary key
2普通索引 index
3唯一索引 unique
4全文索引 fulltext
主键索引
表的唯一主键,不能为null,列不能存在重复数据,唯一索引的一种
普通索引
创建索引
这是最基本的索引,它没有任何限制。它有以下几种创建方式:
\1. 直接创建
CREATE INDEX 索引名 ON 表名(列名(length));
如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。
2.修改表结构(添加索引)
ALTER table 表名 ADD INDEX 索引名(列名)
3.创建表的时候直接指定
CREATE TABLE mytable(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
INDEX [索引名] (username(length)) );
删除索引
通过索引名进行删除
DROP INDEX [索引名] ON 表名;
唯一索引
它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。
创建索引
CREATE UNIQUE INDEX 索引名 ON 表名(字段(length))
修改表结构
ALTER table 表名 ADD UNIQUE [索引名] (字段(length))
创建表的时候直接指定
CREATE TABLE mytable(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
UNIQUE [索引名] (username(length)) );
使用ALTER 命令添加和删除索引
有四种方式来添加数据表的索引:
ALTER TABLE 表名 ADD PRIMARY KEY (列名): 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。
ALTER TABLE 表名 ADD UNIQUE 索引名 (列名): 这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。
ALTER TABLE 表名 ADD INDEX 索引名 (列名): 添加普通索引,索引值可出现多次。
ALTER TABLE 表名 ADD FULLTEXT 索引名 (列名):该语句指定了索引为 FULLTEXT ,用于全文索引。
全文索引
全文索引的索引类型为FULLTEXT。全文索引可以在varchar、char、text类型的列上创建。可以通过ALTER TABLE或CREATE INDEX命令创建。对于大规模的数据集,通过ALTER TABLE(或者CREATE INDEX)命令创建全文索引要比把记录插入带有全文索引的空表更快。MyISAM支持全文索引,InnoDB在mysql5.6之后支持了全文索引。 全文索引不支持中文需要借sphinx(coreseek)或迅搜<、code>技术处理中文。
alter table 表名 add fulltext(字段名);
添加索引使查询效率增快的本质原因,在添加索引后数据库会为该表保存一个只有其索引的表,并将每条数据进行关联(通过这张的每条数据可以找到实际数据的每条数据),在进行查询时,如果筛选条件为添加了索引的列,那么不会再原数据所有列中进行查找,而是在只有索引的列的表中进行查询,但是由于索引维护(在进行数据修改后需要更新索引)所以一般在进行索引添加时只对修改较少的数据添加索引以提升查询速度,而且索引只在使用索引列时生效,如果where字句中既存在索引列判断也存在非索引列判断,那么是索引是无效的(但是任然能少量的提高速度),而且如果索引列判断使用了非确定性判断,那么索引列会失效
jdbc连接数据库
(Java DataBase Connectivity) 用于使用统一的api对数据库数据进行操作
jdbc是java用于操作数据库的根本技术,之后所有的只要是涉及到java与数据库连接的框架、技术都基于jdbc
jdbc是由sun公司提供的对于数据库操作的统一的接口,由不同的数据库厂商进行实现,从而达成根据不同数据库使用相同的方法进行数据库数据的操作。
jdbc连接数据库步骤
1、加载驱动
使用Class.forName加载存放连接数据库的驱动类
2、获取连接
使用DriverManager对象静态方法输入连接地址、账号、密码获取连接对象
3、创建sql声明对象
连接对象创建声明对象方法创建一个sql的执行声明对象
4、将要执行的sql交由sql执行对象执行
根据sql的种类使用不同的执行方法返回相应结果
5、根据执行不同sql
如果执行的ddl 、dml语句则不处理,如果执行的是dql语句需要额外处理结果集对象
6、关闭连接释放资源
如果不是dql则直接关闭连接,否则需要额外关闭结果集对象
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//Java DataBase Connectivity
//java连接数据库技术
public class JDBC {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 使用jdbc连接数据库
// 1、加载驱动类
// 使用反射将指定驱动类加载至虚拟机 使其可以在运行过程中使用
// 且在程序运行期间只需要加载一次
Class.forName("com.mysql.jdbc.Driver");
// 2、获取连接对象
// 使用驱动管理器类 自动使用加载的驱动类进行数据库连接
// 内部存在自动加载相应驱动的方法,但是建议手动加载
// 传入数据类型 url地址 username账号 password密码
// 地址语法jdbc:数据库名://数据库地址ip:端口号/连接的数据库名称;[设置字符编码集]
// 其他数据库连接语法可能稍有不同
// 如果连接成功会返回连接对象
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/teacher", "root", "root");
// 3、使用连接创建执行的声明对象(用于执行sql的对象)
// 可以进行sql的简单编译
// 在使用这个对象进行sql执行时,可以根据连接的数据库进行简单的sql校验
Statement statement = con.createStatement();
// 4、使用声明的对象执行相应的sql返回数据
// execute主要用于执行ddl语句 也可以执行dml、dql语句但是返回boolean类型为是否是查询语句
// executeUpdate用于执行ddl dml sql语句 返回数据类型为int(影响条数)
// executeQuery用于执行dql 语句 返回存储查询结果的结果集
// int executeUpdate = statement.executeUpdate("insert into class
// values(11,'G1T11')");
// 查询返回的结果集对象 是一个存储数据形式类似于set形式的数据集合
ResultSet rs = statement.executeQuery("select * from student");
// rs.next();是否存在下一条数据
while (rs.next()) {// 如果结果集对象中存在数据
// System.out.println(rs.getString(1)+"|\t"+rs.getString(2)+"|\t"+rs.getInt(3)+"|\t"+rs.getString(4)+"|\t"+rs.getString(5)+"|\t"+rs.getString(6)+"|\t");
// get数据类型(列索引) 获取指定列数据转换为指定数据类型并返回
// System.out.println(rs.getString("studentname"));
// get数据类型(列名) 获取指定列名的数据
// 注意 while每次获取的是一行数据
}
// 5、关闭连接
con.close();
}
}
ORM映射框架
Object Relational Mapping
对象关系映射,将数据库的数据与java中的类进行映射,使用java中的类创建对象保存从数据库查询的数据
将数据库的表当做java的类,将数据库的字段当做类的属性进行创建,构建二者之间的关系,通过jdbc连接获取数据库中的数据结果集,解析处理结果集,将返回的结果集对象使用这种映射关系转换为java的集合并存储返回的数据
创建的用于存储数据的类称之为实体类,通常创建相应的包(javabean、pojo)进行保存,仅用于数据库中数据的保存(在程序运行期间)
在进行数据映射时注意保存数据的相应类型进行转换
数据库 =》实体类
varchar=>String
int=>int/Interger
double=>double/Double
日期类型=>sql.Date/sql.timstamp
1根据数据库映射创建实体类
2使用jdbc连接数据库执行查询语句返回结果集
3处理结果集,将结果集中返回数据存储至相应实体类对象中
练习
在进行jdbc连接时,加载驱动获取连接准备sql执行对象这几个步骤重复执行将其封装成工具类简化代码开发
工具类类名jdbcUtil
方法1获取连接方法返回连接对象
方法2返回预编译对象方法
方法3dml语句执行方法 传入执行的sql 返回影响条数
方法4dql语句执行方法 传入执行sql 返回resultSet结果集对象
方法5关闭方法 传入连接对象 结果集对象 将结果集、连接关闭
注意:本文归作者所有,未经作者允许,不得转载