从尿检取中段谈数据库压测

less than 1 minute read

背景

想必大家都参加过一年一次的体检,在进行尿液体检的时候,医生会告诉你要留中段尿!要留中段尿!要留中段尿!重要的事情说三遍。

为什么尿液化验要取中段尿呢?

因为前段尿和后段尿容易被污染,所以在进行尿常规和尿培养检查时都建议留取中段尿。

我们在做数据库压测时,也会遇到类似的情况,比如一个持续数天的TPCC压测,tps在时间曲线上的表现可能会是这样的:

开始时tps缓慢的攀升,然后会经过一个较长时间的平稳期,(期间可能还有有一些短暂的抖动),最后又会以非常平缓的曲线开始性能慢慢下降。

简单分析

前段TPS攀升的原因,

开始时TPS缓慢攀升,是因为数据库的shared buffer还没有被填满,所有的查询都是从块设备直接读取的,所以由于块设备和内存访问速度的差异造成了一开始的速度会较慢。

然后随着数据库shared buffer的填充,以及OS层cache的填充(如果没有使用DIO),命中率高了之后,RT会下降,TPS自然就升上去了。

中段TPS平稳的原因,

数据库的shared buffer和os cache都被热数据填充,所以在TPCC压测时,RT是比较均匀的。

期间TPS抖动的原因,

数据库在产生了一定数量的脏页后,需要将做检查点,将shared buffer的脏页刷回磁盘,所以会增加额外的分段批量写IO的操作(检查点的IO优化操作在此文不展开,我以前有针对PostgreSQL检查点的优化写过文章),特别是两个检查点之间的脏页很多时,抖动会较为明显。

后段TPS下降的原因,

因为TPCC涉及到较多的更新和插入操作。

随着数据不断的插入,表的数据量变大后,对应的索引的层次可能会变深,层次变深后,通过索引访问数据需要扫描的块就会增加,这是影响性能的原因之一。

另一方面,随着数据的更新,垃圾tuple会增加到一定的量,同时索引可能会膨胀,深度变深。需要访问的页数增加,也是导致性能下降的原因之一。

并不是所有的压测都会出现后段性能下降的情况,例如只读的场景,就不会出现后段的问题。

对于写入和更新的场景,如果控制好表的大小,如使用分区,也不会出现后段的情况,因为索引页的深度是可控的。

例如一组这样的测试结果,每轮测试2分钟,连续测n轮。

    transactions:                        147549 (1035.36 per sec.)  
    transactions:                        149521 (1245.82 per sec.)  
    transactions:                        159201 (1326.20 per sec.)  
    transactions:                        152378 (1268.96 per sec.)  
    transactions:                        153969 (1282.87 per sec.)  
    transactions:                        154719 (1289.09 per sec.)  
    transactions:                        160117 (1333.84 per sec.)  
    transactions:                        161628 (1346.59 per sec.)  
    transactions:                        160033 (1332.50 per sec.)  
    transactions:                        154718 (1289.12 per sec.)  
    transactions:                        155586 (1296.09 per sec.)  
    transactions:                        153503 (1278.71 per sec.)  
    transactions:                        151012 (1258.08 per sec.)  
    transactions:                        162499 (1353.82 per sec.)  
    transactions:                        153878 (1281.24 per sec.)  
    transactions:                        158137 (1317.45 per sec.)  
    transactions:                        157630 (1312.76 per sec.)  
    transactions:                        151530 (1262.64 per sec.)  
    transactions:                        152966 (1274.54 per sec.)  
    transactions:                        154235 (1284.25 per sec.)  
    transactions:                        153674 (1280.25 per sec.)  
    transactions:                        152721 (1272.19 per sec.)  
    transactions:                        154113 (1284.07 per sec.)  
    transactions:                        162871 (1356.21 per sec.)  
    transactions:                        150610 (1254.76 per sec.)  
    transactions:                        152196 (1267.36 per sec.)  
    transactions:                        158429 (1319.31 per sec.)  
    transactions:                        152625 (1271.77 per sec.)  
    transactions:                        159619 (1329.89 per sec.)  

建议也是取中段,去掉最低值和最高值,取平均值。

Flag Counter

digoal’s 大量PostgreSQL文章入口