map

使用 map 关键字,SQL 语句会在每个分区内分别执行,然后输出每个分区的执行结果。

适合使用 map 关键字的场景:

场景一:需要在每个分区内进行查询的场景(见 Example 1)

场景二:分组查询计算提升性能(见 Example 2)

对分组数据进行查询和计算时,通常先在各个分区单独计算,然后将结果进行进一步计算以保证最终结果的正确性。如果分区的粒度大于分组的粒度,从而可以确保数据的查询和计算不会跨分区进行,则可添加 map 关键字,避免进一步计算的开销,从而提升查询性能。

注意:SQL where 子句中一般不允许使用聚合函数或序列相关函数,原因在于,若允许则会进行全表扫描计算,无法进行分区剪枝。但若使用 map 关键字,则允许在 where 子句中使用聚合函数或序列相关函数, 在每个分区内部进行指定计算以过滤记录。(见 Example 3)

例子

Example 1. 分区计算

$ t = table(0..9 as id, take(1 2 3, 10) as qty)
$ db=database("dfs://rangedb", RANGE, 0 5 10)
$ pt = db.createPartitionedTable(t, `pt, `id)
$ pt.append!(t);

$ select * from pt;

id

qty

0

1

1

2

2

3

3

1

4

2

5

3

6

1

7

2

8

3

9

1

$ select first(id), count(*) from pt map;

first_id

count

0

5

5

5

Example 2. 合理使用 map 关键字有助于在分组查询和计算时提升性能。

$ t = table(2022.01.01T00:00:00 + rand(10000000, 10000) as dateTime, rand(1000, 10000) as qty)
$ if(existsDatabase("dfs://valuedb")) dropDatabase("dfs://valuedb")
$ db=database("dfs://valuedb", VALUE, 2022.02.01..2022.02.05)
$ pt = db.createPartitionedTable(t, `pt, `dateTime)
$ pt.append!(t)

$ timer(1000) select count(*) from pt group by bar(dateTime, 60)
Time elapsed: 4010.31 ms

$ timer(1000) select count(*) from pt group by bar(dateTime, 60) map
Time elapsed: 3607.331 ms

Example 3. 跨分区查询时,指定 map 关键字,以支持在 where 子句中使用聚合函数或者序列相关函数进行条件过滤。

$ t = table(0..9 as id, take(1 2 3, 10) as qty)
$ db=database("dfs://rangedb", RANGE, 0 5 10)
$ pt = db.createPartitionedTable(t, `pt, `id)
$ pt.append!(t);

$ select * from pt where isDuplicated([id,qty]) = false map;

id

qty

1

1

1

2

2

1

2

5

2

2