背景形容:
组内我的项目有一张表叫做Session,记录的是每一条测试的详细信息,包含id,创建者,创立工夫,测试时长,测试状态(FINISH,TESTING,NO_FRAME等),还有Properties(是一个大json,也就是什么字段都能够往里面塞,例如我的项目包名,软件版本号,测试各项配置)等。
当初须要加一个性能,这个性能是在admin页面上,也就是后盾治理页面上做的。当你在页面上hover某条测试的包名(例如:com.hhh.goodgame)的时候,须要显示该测试包,在咱们我的项目内实现了多少次测试。
最开始的做法就是失常的调用ListSession函数,并传入参数进去,取得api返回的count数。
http.listSessions({equalPackageName:searchedSession.Properties.packageName,testStatus:'FINISHED', withDelete: true})
然而,因为Session列表的数目过于大,有15w条数据,所以每次查问速度都很慢。于是,咱们决定在Properties.packageName字段下面,建设一个索引。最开始的时候,我还在纠结能不能给字段的字段建设索引,起初查了一下,PSQL真的很弱小,它能够反对:表达式索引。
create index idx_session_properties_packagename on upa.profilingsession ((properties ->> 'packageName'));
建设好索引之后,就是验证它是否失效了。在将我的liquibase批改推向master分支之前,我在本地的数据库里进行了模仿。
点开表的详情曾经能够看失去了。而后,决定再用explain试一下,看看index是否有被好好应用,然而后果如下图所示。
而后,我就很奇怪,为什么明明表详情内曾经能够看到index idx_session_properties_packagename,然而搜寻的时候却没有用上。于是猜测,是不是因为我本地表内数据只有7行,数据量太小了?于是我怒插20行,最终失去了如下图所示的后果。
总结学习:
1)新增的 index 並沒有在 query plain 裡面。為什麼postgres不選擇index scan卻選擇seq scan?
在數據量很小的時候, seq scan 會比 index scan 更加无效。
pgsql 的 query plan 有一個評估值的形式來 “預測” 哪一種形式比較快。index scan 至多要發生兩次 I/O,一次是讀取索引塊,一次是讀取數據塊,代價遠高於 seq can。當 index 很大的時候,情況可能會更加複雜。
2)postgresql中的各种scan的比拟
- Seq Scan(就是依照表的记录的排列程序从头到尾顺次检索扫描,每次扫描要取到所有的记录。这也是最简略最根底的扫表形式,扫描的代价比拟大)
- Index Scan(对于给定的查问,咱们先扫描一遍索引,从索引中找到符合要求的记录的地位(指针),再定位到表中具体的Page去取。等于是两次I/O,先走索引,再走取表记录,不同于全表扫描的是只取所需数据对应的Page,I/O量较小)
- Bitmap Heap Scan(当 PostgreSQL 须要合并索引拜访的后果子集时 会用到这种形式 ,通常状况是在用到 "or",“and”时会呈现"Bitmap heap scan")
- index only scan(建设 index时,所蕴含的字段汇合,囊括了咱们查问语句中的字段,这样,提取出相应的index ,就不用再次提取数据块了)
- 当获取的数据分布很大(比方70%以上)时,用index scan 曾经没有意义了,因为数据太多了,走索引再走表的代价曾经超过了单纯走表的代价了。就不如用全表扫描了。
- 而数据分布较小(比方 1.7%),则索引的劣势就体现进去了。可能bitmap index scan的性能就更好(相比于index scan,因为它缩小了index的反复扫描)。
- 当数据更少的时候,用index scan可能就更好(索引反复的可能性较小且回避了在内存中排序的代价)。