热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AndroidSQLite数据库进行查询优化的方法

前言数据库的性能优化行业里面普遍偏少,今天这篇希望给大家带来点帮助SQLite是个典型的嵌入式DBMS,它有很多优点,它是轻量级的,在编译之后很

前言

数据库的性能优化行业里面普遍偏少,今天这篇希望给大家带来点帮助

SQLite是个典型的嵌入式DBMS,它有很多优点,它是轻量级的,在编译之后很小,其中一个原因就是在查询优化方面比较简单

我们在使用SQLite进行数据存储查询的时候,要进行查询优化,这里就会用到索引,C端的数据量大部分情况下面虽然不是很大,但良好的索引建立习惯往往会带来不错的查询性能提升,同时在未知的将来经得住更大数据的考验,那如何优化数据库查询呢,下面我们用例子一一演示下。

先建个测试表table1,包含了三个索引:

sqlite> .schem
CREATE TABLE table1(id integer primary key not null default 0,a integer,b integer, c integer);
CREATE INDEX a_i on table1 (a);
CREATE INDEX a_i2 on table1 (a,b);
CREATE INDEX a_i3 on table1 (c);

在常见的数据库系统里面,进行SQL查询检验都是用explain关键字,比如:

sqlite> explain select * from table1;
addr opcode   p1 p2 p3 p4    p5 comment  
---- ------------- ---- ---- ---- ------------- -- -------------
0  Init   0  10 0     00 Start at 10 
1  OpenRead  0  2  0  4    00 root=2 iDb=0; table1
2  Rewind   0  9  0     00    
3  Rowid   0  1  0     00 r[1]=rowid 
4  Column   0  1  2     00 r[2]=table1.a
5  Column   0  2  3     00 r[3]=table1.b
6  Column   0  3  4     00 r[4]=table1.c
7  ResultRow  1  4  0     00 output=r[1..4]
8  Next   0  3  0     01    
9  Halt   0  0  0     00    
10 Transaction 0  0  4  0    01 usesStmtJournal=0
11 Goto   0  1  0     00 

立马就会得到输出,这些输出表示SQLite执行这条SQL用到的每句指令,这个其实不怎么直观,我们用到更多的是EXPLAIN QUERY PLAN,如下:

sqlite> explain QUERY PLAN select * from table1;
0|0|0|SCAN TABLE table1

这条SQL语句是查询了整张表,所以结果关键字SCAN表示要完整遍历,这种效率是最低的,接下来我们试试加个查询条件:

sqlite> explain QUERY PLAN select * from table1 where a=1;
0|0|0|SEARCH TABLE table1 USING INDEX a_i2 (a=?)

加上where a=1之后关键字变成了SEARCH,表示不再需要遍历了,而是使用了索引进行了部分检索,另外这条输出还有更多信息,比如使用了索引a_i2,而括号里面的a=?则表示是这个查询条件引起的

我们稍微修改下SQL:

sqlite> explain QUERY PLAN select a from table1 where a=1;
0|0|0|SEARCH TABLE table1 USING COVERING INDEX a_i (a=?)

把select 变成了select a,发现explain输出有细微变化,从INDEX变成了COVERING INDEX,CONVERING INDEX表示直接使用索引查询就可以得到结果,不需要再次回查数据表,这样效率更高。而之前的查询因为是使用,索引里面只有a记录,所以必须要查询原始记录才能得到b,c字段。我们再试下这条SQL:

sqlite> explain QUERY PLAN select a,b from table1 where a=1 and b=1;
0|0|0|SEARCH TABLE table1 USING COVERING INDEX a_i2 (a=? AND b=?)

同意因为索引a_i2已经包含a和b了,所以也是使用CONVERING INDEX。那有同学可能会问了,那我们建索引的时候都把其他字段都加进去呗,虽然查询用不到,但不用二次查询原始记录效率高。理论上这样是可行的,但这里有个重要问题就是数据冗余太严重了,导致索引和原始数据一样大,在海量数据存储的数据库里面磁盘消耗是个问题,所以如何选择可能要做个平衡。

接下来我们把and换成or:

sqlite> explain QUERY PLAN select a,b from table1 where a=1 or b=1;
0|0|0|SCAN TABLE table1 USING COVERING INDEX a_i2

发现又变回SCAN了,但仍然使用到了索引a_i2,对比下这条SQL:

sqlite> explain QUERY PLAN select a,b from table1 where a=1;
0|0|0|SEARCH TABLE table1 USING COVERING INDEX a_i2 (a=?)

多了个查询条件b=1之后效率变差了,这是为什么呢?这里要引出我们创建索引使用的最关键的原则:前缀索引。

索引一般是使用B树,前缀索引简单来讲,就是要想能使用这个索引,查询条件必须满足索引建立涉及到的字段,并且和查询使用的顺序一致。

我们回头看刚才那个or的例子,对于查询条件a=1,他能使用a_i2(a,b)这个索引,因为索引顺序也是a开头的。但or的例子里面还或上一个查询条件b=1,对于这个查询就没有索引可以用了,因为没有b开头的索引存在。a_i2(a,b)这个索引里面虽然有b,但b对于b=1这个查询条件来说不是在前面,不满足前缀索引原则。

而对于刚才那个and的例子,则能够完全使用索引,因为存在索引a_i2(a,b),可以想象成先按索引a过滤数据,剩下数据再用索引b过滤数据。对于and条件来说,索引里面字段的顺序换一下也是没有关系的,数据库会自动优化选择,比如:

sqlite> .schem
CREATE INDEX a_i22 on table2 (b,a);
sqlite> explain QUERY PLAN select a,b from table2 where a=1 and b=1;
0|0|0|SEARCH TABLE table2 USING COVERING INDEX a_i22 (b=? AND a=?)

如果or查询也要充分使用索引,聪明的读者一定想到了,那就是要建2个索引,如下:

CREATE TABLE table3(id integer primary key not null default 0,a integer,b integer, c integer);
CREATE INDEX a_i222 on table3(a);
CREATE INDEX a_i2222 on table3(b);
sqlite> explain QUERY PLAN select a,b from table3 where a=1 or b=1;
0|0|0|SEARCH TABLE table3 USING INDEX a_i222 (a=?)
0|0|0|SEARCH TABLE table3 USING INDEX a_i2222 (b=?)

我们再来看一个进阶的,加上一个排序:

CREATE TABLE table1(id integer primary key not null default 0,a integer,b integer, c integer);
CREATE INDEX a_i2 on table1 (a,b);

sqlite> explain QUERY PLAN select a,b from table1 where a=1 order by b;
0|0|0|SEARCH TABLE table1 USING COVERING INDEX a_i2 (a=?)


CREATE TABLE table3(id integer primary key not null default 0,a integer,b integer, c integer);
CREATE INDEX a_i222 on table3(a);
CREATE INDEX a_i2222 on table3(b);

sqlite> explain QUERY PLAN select a,b from table3 where a=1 order by b;
0|0|0|SEARCH TABLE table3 USING INDEX a_i222 (a=?)
0|0|0|USE TEMP B-TREE FOR ORDER BY

对比这2个查询,发现下面这个多了个USE TEMP B-TREE FOR ORDER BY。对于第一个查询来说,我们可以看到排序也是同样满足前缀索引原则(先按索引a过滤数据,剩下数据用索引b排序)。对于第二个查询来说,因为不满足这个原则导致多了个临时表来做排序。看到这里大家应该理解前缀索引的意思了。

我们再看这个样子,把查询条件和排序换下:

sqlite> explain QUERY PLAN select a,b from table1 where b=1 order by a;
0|0|0|SCAN TABLE table1 USING COVERING INDEX a_i2

显然不满足前缀索引原则了,因为需要先按索引b过滤数据,但b不是第一个。

常规的查询语句大部分是and,or,order的组合使用,只需要掌握上面说的原则,一定能写出高性能的数据库查询语句来。

而对于更高级的一些连表可以继续翻阅官方文档:

https://www.sqlite.org/eqp.html

https://www.sqlite.org/lang_e...

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对编程笔记的支持。


推荐阅读
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 开源Keras Faster RCNN模型介绍及代码结构解析
    本文介绍了开源Keras Faster RCNN模型的环境需求和代码结构,包括FasterRCNN源码解析、RPN与classifier定义、data_generators.py文件的功能以及损失计算。同时提供了该模型的开源地址和安装所需的库。 ... [详细]
  • 在IDEA中运行CAS服务器的配置方法
    本文介绍了在IDEA中运行CAS服务器的配置方法,包括下载CAS模板Overlay Template、解压并添加项目、配置tomcat、运行CAS服务器等步骤。通过本文的指导,读者可以轻松在IDEA中进行CAS服务器的运行和配置。 ... [详细]
  • 求解连通树的最小长度及优化
    本文介绍了求解连通树的最小长度的方法,并通过四边形不等式进行了优化。具体方法为使用状态转移方程求解树的最小长度,并通过四边形不等式进行优化。 ... [详细]
author-avatar
我似1998
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有