在此次测试中数据库表有三个字段,id(自增主键)、username、password。
图1
实测:
import mapper.TestMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import po.TestBean;
import java.io.IOException;
import java.io.InputStream;
public class MybatisTest {
public static void main(String[] args) throws IOException {
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
TestMapper testMapper = session.getMapper(TestMapper.class);
//5.使用代理对象执行方法
TestBean testBean =new TestBean();
for (int i = 10; i<20000000 ;i++){
testBean.setName("lbw"+i);
testBean.setPassword("nb"+i);
testMapper.saveTest(testBean);
// //1次操作 提交1次事务
// session.commit();
// 100000次操作提交1次事务
if (i%100000 == 0){
session.commit();
}
}
//6.释放资源
session.close();
in.close();
}
}
package po;
import java.io.Serializable;
public class TestBean implements Serializable {
String id;
String name;
String password;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "po.TestBean{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
package mapper;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import po.TestBean;
public interface TestMapper {
@Insert("insert into test200411(name,password) values(#{name},#{password})")
void saveTest(TestBean t);
@Select("select id,name,password from test200411 where id = #{s}")
TestBean selectById(String s);
}
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
dataSource>
environment>
environments>
<mappers>
<mapper class="mapper.TestMapper"/>
mappers>
configuration>
程序运行后在几个小时时间里,电脑处于烤机(烤鸡诱惑,烤鸡pg是块宝)状态!!!很遗憾的是,当时没有截图程序运行了的时间,不过1.1结论是数据是保真的,实在不想再搞几千万条数据在数据库了。
图3
图4
使用 select count(0) from test200411
进行计数,统计查询用时:13.7s,得到统计数: 20379620,之所以是20379620,是因为我测试中先插入30多万,之后再插入2000万。数据是不会骗人的哦,没毛病吧,铁子们。
图5
使用 show index from test200411
可以查到当前表拥有的索引,当前只有我自己自增id的默认索引,和我自己建立的id字段索引。
图8
使用 SELECT * from test200411 where password = "nb1234"
查询到两条数据,耗时:57.9s,明显这个查询时间是不可取的
使用:SELECT * from test200411 where id = 2566345
查询到唯一数据,耗时:0.133s
使用:CREATE INDEX paw_index ON test200411(
password)
耗时:156.0s
图11
再次查看已经索引,可以看到一个paw_index 的新索引,这就是我们刚刚创建的索引。
图12
使用 SELECT * from test200411 where password = "nb12345"
耗时:0.110s
可以将此条sql和 2.2.1 比较 ,除了匹配的字符串不一样(之所以用了不同的字符串,是因为实验是连着做的,同一条字符串查询,会有缓存,影响结果),其他都是一样的。可以看到它们之前惊人的查询速度差异,速度相差大概是500倍。
图13
在一个事务内只提交一条sql和在一个事务内提交多个sql,对数据库数据的批量处理影响是很大的。
一个事务内提交多个sql可以提高批量数据的处理速度。
通过上面的实例,我们可以看到,有无索引对数据库查询速度的影响是很大的,实验中它们速度差异可以到500倍,当然这是取决的实验过程中的数据量,而我们的实验数据量有2000多万行,也正是这样才能放大对 有无索引对数据库查询的影响 效果。
总之,通过这个实例不会有人还没搞懂索引这个东西的重要性和其作用吧!不会吧?不会吧?
当然我这没将索引的三板斧,“是什么,为什么需要,怎么做”,全列出来,我觉得写也的还行,带有实例出发,通俗易懂吧!!
这个实验从上到下都是可以复现的,代码和过程都有,有兴趣的小伙伴可以尝试复现一下,让自己对索引的理解加深。
最后,若是小伙伴有什么问题,可以一起讨论哦。。。。。