移动端100万数据sqlite语句的搜索查询优化(索引篇)

数据库的优化,最大的一点:索引的建立,那么你写过这么多的sql语句,真的会用索引么,或者说会用索引么?体验过百万级别的查询速度么?

为什么要使用索引?
索引能够加速表中数据的查找和排序,索引是一个单独建立  的物理数据库,并且包含
一个指向数据表中指定列的数据值指针(指向对应数据的指针)。
作用:
1. 快速查询数据
2.保证数据的唯一性
3. 实现表与表之间的参照完整性
4.在使用order by、group by子句进行数据检索时,利用索引  可以减少排序和分组的时间。
优点:
1. 大大加快数据检索速度
2. 创建唯一索引,保证数据库表中每行数据的唯一性
3. 加速表之间的连接
4. 减少查询中分组和排序的时间
缺点:
1.需要占用物理空间
2. 对表中数据进行增加、删除和修改时索引也要更新,降低了数据维护速度

一.索引的分类(聚集索引,非聚合索引,复合索引)

1.聚集(clustered)索引,也叫聚簇索引。

定义:表中行的物理顺序与键值的逻辑(索引)顺序相同。因为数据的物理顺序只能有一种,所以一张表只能有一个聚集索引。如果一张表没有聚集索引,那么这张表就没有顺序的概念,所有的新行都会插入到表的末尾。对于聚集索引,叶节点即存储了数据行,不再有单独的数据页。

定义比较抽象,举个实际的例子:
一个表就像是我们以前用的新华字典,聚集索引就像是拼音目录,而每个字存放的页码就是我们的数据物理地址,我们如果要查询一个“哇”字,我们只需要查询“哇”字对应在新华字典拼音目录对应的页码,就可以查询到对应的“哇”字所在的位置,而拼音目录对应的A-Z的字顺序,和新华字典实际存储的字的顺序A-Z也是一样的,如果我们中文新出了一个字,拼音开头第一个是B,那么他插入的时候也要按照拼音目录顺序插入到A字的后面
下面看个数据,解释下数据物理地址:

地址  id  username    age
0x01    1   小张      11
0x02    2   小红      12
0x03    3   小华      11
..  ..  ..  ..
0xff    256 小英      12
第一列的地址表示该行数据在磁盘中的物理地址,后面三列才 是我们SQL里面用的表里的列,
其中id是主键,建立了聚集索引.结合上面的表格就可以理解这句话了吧:数据行的物理顺序与列值的顺序相同,
如果我们查询id比较靠后的数据,那么这行数据的地址在磁盘中的物理地址也会比较后,而且由于物理排列方式与聚集索引的顺序相同,所以也就只能建立一个聚集索引了.

不理解?咱们再用图来说明


满二叉树

树节点1下面有2和2的节点,也可以看作数据节点,是不是可以直接获取到对应的全部列的数据?这个就是聚集索引所有的优势

2.创建聚集索引(注:Sqlite不支持聚集索引)

2.1.  如果不创建索引,系统会自动创建一个隐含列作为表的聚集索引。
create table t1(
    id int primary key,
    name nvarchar(255)
)
2.2.创建表后添加聚集索引
SQL Server
    create clustered index clustered_index on    table_name(colum_name)
MySQL
    alter table table_name add primary key(colum_name)

  值得注意的是,最好还是在创建表的时候添加聚集索引,由于聚集索引的物理顺序上的特殊性,    
  因此如果再在上面创建索引的时候会根据索引列的排序移动全部数据行上面的顺序,会非常地耗费时间以及性能。

二.非聚集索引

    定义:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非
聚集索引。

可以这样理解:除了聚集索引以外的索引都是非聚集索引,只是人们想细分一下非聚集索引,
分成普通索引,唯一索引,全文索引。如果非要把非聚集索引类比成现实生活中的东西,那
么非聚集索引就像新华字典的偏旁字典,他结构顺序与实际存放顺序不一定一致。

通俗点的理解就是:索引节点跟聚集节点是一样的,只是查询的时候,定义的索引在其他列上并没有覆盖,这时候还得去这个没有覆盖的列上再查询,这就需要二次查询了

    标准的说法是:非聚集索引叶节点仍然是索引节点,只是有一个指针指向对应的数据块,此如
果使用非聚集索引查询,而查询列中包含了其他该索引没有覆盖的列,那么他还要进行第二
次的查询,查询节点上对应的数据行的数据。

举个例子:   
id    username        age
1        小张          11
2        小红          12
3        小华          11
..          ..            ..
256      小英          12

以及聚集索引clustered index(id), 非聚集索引index(username)。

使用以下语句进行查询,不需要进行二次查询,直接就可以从非聚集索引的节点里面就可以获取
到查询列的数据。

select id, username from t1 where username = '小张'
select username from t1 where username = '小张'
但是使用以下语句进行查询,就需要二次的查询去获取原数据行的score:
select username, age from t1 where username = '小张'

如何解决非聚集索引的二次查询问题?使用复合索引

三:复合索引(索引生效讲解)

复合索引(覆盖索引)顾名思义就是建立两列以上的索引,即可查询复合索引里的列的数据而不需要进行回表二次查询,如index(col1, col2),执行下面的语句:
select col1, col2 from t1 where col1 = 'xxx';

注意:在查询使用时,最好将条件顺序按找索引的顺序,这样效率最高

举些例子:

 CREATE INDEX index_table ON table(x, y, z)创建索引
 那么x,xy,xyz都是前导列,而yz,y,z这样的就不是

索引生效的条件:

  前序列必须使用等于或者in操作最右边的列可以使用不等式,这样索引才可以完全生效。
同时,where子句中的列不需要全建立了索引,但是必须保证建立索引的列之间没有间隙
   CREATE INDEX idx_ex1 ON ex1(a,b,c,d,e,...,y,z);

   WHERE a=5 AND b IN (1,2,3) AND c IS NULL AND d='hello'
这显然对于abcd四列都是有效的,因为只有等于和in操作,并且是前导列。

再看三个查询语句:
WHERE a=5 AND b IN (1,2,3) AND c>12 AND d='hello'
那这里只有a,b和c的索引会是有效的,d列的索引会失效,因为它在c列的右边,而c列使用
了不等式,根据使用不等式的限制,c列已经属于最右边。
WHERE b=5 AND c=3 AND d =  'hello'
不生效,没有按照索引顺序
WHERE  d =  'hello'
不生效,没有按照索引顺序

最后再看一条:
WHERE b IN (1,2,3) AND c NOT NULL AND d='hello'
索引将不会被生效,因为没有使用前导列,a不在,这个查询会是一个全表查询。

对于between,or,like,都无法使用索引。必须要用对应的等式来生效索引

between:
WHERE scope BETWEEN 100 and 202;
这时就应该将其转换成:
WHERE scope >= 10 AND scope <= 20;

like:
index_table WHERE scope LIKE 'sql%';;
此时应该将它转换成:
WHERE scope >= 'sql' AND scope < 'xxx';

or(用in):
WHERE scope = 'abc' OR scope = 'xyz';
此时应该将它转换成:
WHERE scope IN ('abc', 'xyz');
聚集和非聚集索引区别

总结:
1.使用聚集索引的查询效率要比非聚集索引的效率要高,但是如果需要频繁去改变聚集索引的值,写入性能并不高,因为需要移动对应数据的物理位置。
2.非聚集索引在查询的时候可以的话就避免二次查询,这样性能会大幅提升。
3.索引有助于提高检索性能,但过多或不当的索引也会导致系统低效。因为用户在表中每加进一个索引,数据库就要做更多的工作。过多的索引甚至会导致索引碎片

联想问题?:
复合索引会替代单一索引么?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容