【性能优化】5.2 [有序遍历] DISTINCT 和 COUNT(DISTINCT)
5.2 DISTINCT 和 COUNT(DISTINCT)
SQL 中的 DISTINCT 和 COUNT(DISTINCT) 一直是拖累性能的常见问题。DISTINCT 本质上是没有汇总项的分组汇总运算,在数据无序时确实不好做,这需要把遍历过的分组键值都保持住用于后续的比对,如果结果集太大还要像前面介绍大分组时那样做缓存,性能低下。
数据有序时,就可以使用上节说的有序分组方法来计算 DISTINCT 了。
如果我们事先把 orders.ctx 表按 id 排序后,再来计算 id 的去重结果:
A |
|
1 |
=file("orders.ctx").open().cursor(id;amount>1000) |
2 |
=A1.group(id) |
没有汇总项的 group 本质上就是 DISTINCT。这里会返回成游标以适合数据量很大的情况。
COUNT(DISTINCT) 的情况要稍复杂一些。如果简单地对全集做 COUNT(DISTINCT),那只要对 DISTINCT 的结果做个计数就可以了。
3 |
=A2.skip() |
更常见的 COUNT(DISTINCT) 会应用到针对其它键值的分组中,比如统计每月的帐户数量。
A |
|
1 |
=file("orders.ctx").open().cursor(id,dt;amount>1000) |
2 |
=A1.groups(month@y(dt);icount@o(id)) |
数据对 id 有序时,可以使用 icount@o 来计算 COUNT(DISTINCT),这时候 SPL 将不会再保持所有遍历过的 id 值,而会采用有序分组的方法,只保持上一个 id 值用于比对。占用内存要小得多,计算性能也快得多。