高并发帐户查询怎么才能跑得快?
高并发帐户查询,是要在几千万甚至几亿的帐户历史数据中,快速找到某个帐户的几条到几千条明细。计算很简单,把数据查出来就可以了,关键是大并发时,响应速度要达到秒级甚至更快!
在数据库中,用索引查找单个帐户的速度很快,几乎感觉不到,但并发很多时就会有明显延迟了。原因是数据库不能保证同一帐户的数据在物理上会连续存放,很可能是乱序的。而硬盘有最小读取单位,在读不连续数据时,会取出很多无关内容,查询就会变慢。虽然每个帐户数据量很少,但是高并发访问的每个查询都慢一点,总体性能就会很差了。
解决这个问题的关键就是把数据按照帐户排序,保证同一帐户的数据连续存储,查询时从硬盘上读出的数据块几乎都是目标值,性能就会得到大幅提升。
但是,大多数数据库不容易保证数据存储的物理次序,就难以应用这个方法。
使用开源集算器 SPL 可以方便地实现这个方案,SPL 代码如下:
1. 先建立行存有序文件,实现物理连续存储:
file("T.ctx").create@r(#id,tdate,amt,…).append@i(file("T-original.ctx").cursor().sortx(id))
特别要注意的是,这时候要采用行式存储,而不是很多数据仓库鼓吹的列存方案,因为列存时各列连续存储,一个帐户的字段分散在不同的列中,还是会造成硬盘读取不连续数据的情况。特别是有并发任务时,列存造成的硬盘不连续访问程度要比行存严重的多。
集算器同时支持行存和列存,可以根据需要选择数据的存储方案。
2. 然后就可以进行高并发帐户查询:
T.icursor(id,tdate,amt,...;id==10100 && tdate>=date("2021-01-10") && tdate
在同等硬件环境下,用 SPL 实现的这种方案比 Oracle 快了 26 倍!
3. 再进一步,还可以把需要查询的少量字段值冗余到索引中,这样就不用从原表取数了,性能会更快。建立带值索引:
file("T.ctx").index(index_id;id;tdate,amt,…)
之后的查询是一样的。
更详细的实现方法在这里: [SQL 提速:高并发帐户查询](https://c.raqsoft.com.cn/article/1635390066386)
还有方案和实测数据: [高并发 - 有关联查询 - 性能优化](https://c.raqsoft.com.cn/article/1574912498366)
英文版