ํ ์ด๋ธ ํ์ Java UDF(UDTF)ยถ
์ด ๋ฌธ์๋ Java์์ UDTF(์ฌ์ฉ์ ์ ์ ํ ์ด๋ธ ํจ์ )๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํฉ๋๋ค.
์ด ํญ๋ชฉ์ ๋ด์ฉ:
์๊ฐยถ
Java UDTF ์ฒ๋ฆฌ๊ธฐ ํด๋์ค๋ UDTF ํธ์ถ์์ ์์ ํ ํ์ ์ฒ๋ฆฌํ๊ณ ํ ์ด๋ธ ํ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค. ์์ ๋ ํ์ Snowflake์ ์ํด ์์์ ์ผ๋ก ๋ถํ ๋๊ฑฐ๋ ํจ์ ํธ์ถ ๊ตฌ๋ฌธ์์ ๋ช ์์ ์ผ๋ก ๋ถํ ๋ฉ๋๋ค. ํด๋์ค์์ ๊ตฌํํ๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋ณ ํ๋ฟ ์๋๋ผ ํ์ด ๊ทธ๋ฃนํ๋ ํํฐ์ ๋ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
์ฒ๋ฆฌ๊ธฐ ํด๋์ค๋ ๋ค์์ ์ฌ์ฉํ์ฌ ํํฐ์ ๊ณผ ํ์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
์ด๋์ ๋ผ์ด์ ๋ก ์ฌ์ฉ๋๋ ์ธ์ ์๋ ์์ฑ์. ์ด ์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ ํํฐ์ ๋ฒ์ ์ง์ ์ํ๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
๊ฐ ํ์ ์ฒ๋ฆฌํ๋
process
๋ฉ์๋.๋ฒ์ ์ง์ ๋ ๊ฐ์ ํํฐ์ ์ผ๋ก ๋ฐํํ๋ ๊ฒ์ ํฌํจํ์ฌ, ํํฐ์ ์ฒ๋ฆฌ๋ฅผ ์๋ฃํ๊ธฐ ์ํ ํ์ด๋๋ผ์ด์ ๋ก ์ฌ์ฉ๋๋ ์ธ์ ์๋
endPartition
๋ฉ์๋.
์์ธํ ๋ด์ฉ์ ์ด ํญ๋ชฉ์ UDTFs์ฉ Java ํด๋์ค ์น์ ์ ์ฐธ์กฐํ์ญ์์ค.
๊ฐ Java UDTF์๋ ํธ๋ค๋ฌ ํด๋์ค์ ์ํด ์์ฑ๋ ์ถ๋ ฅ ํ ์ด์ Java ๋ฐ์ดํฐ ํ์ ์ ์ง์ ํ๋ ์ถ๋ ฅ ํ ํด๋์ค ๋ ํ์ํฉ๋๋ค. ์์ธํ ๋ด์ฉ์ ์ด ํญ๋ชฉ์ ์ถ๋ ฅ ํ ํด๋์ค ์น์ ์ ํฌํจ๋์ด ์์ต๋๋ค.
๋ถํ ์ ๋ํ ์ฌ์ฉ๋ฒ ๋ ธํธยถ
Snowflake์์ ์์์ ์ผ๋ก ๋ถํ ๋ ํ์ ์์ ํ ๋๋ ์ฒ๋ฆฌ๊ธฐ ์ฝ๋๊ฐ ํํฐ์ ์ ๋ํด ์ด๋ค ๊ฐ์ ๋ ํ ์ ์์ต๋๋ค. ์์์ ๋ถํ ๊ณผ ํจ๊ป ์คํํ๋ ๊ฒ์ UDTF๊ฐ ์ถ๋ ฅ ์์ฑ์ ์ํด ๊ฐ๋ณ์ ์ผ๋ก ํ๋ง ๋ณผ ํ์๊ฐ ์๊ณ ํ ๊ฐ์ ์ง๊ณ๋ ์ํ๊ฐ ์๋ ๊ฒฝ์ฐ์ ๊ฐ์ฅ ์ ์ฉํฉ๋๋ค. ์ด ๊ฒฝ์ฐ ์ฝ๋์๋ ์๋ง ์์ฑ์๋
endPartition
๋ฉ์๋๊ฐ ํ์ํ์ง ์์ ๊ฒ์ ๋๋ค.์ฑ๋ฅ์ ํฅ์ํ๊ธฐ ์ํด Snowflake๋ ์ผ๋ฐ์ ์ผ๋ก UDTF ํธ๋ค๋ฌ ์ฝ๋์ ์ฌ๋ฌ ์ธ์คํด์ค๋ฅผ ๋ณ๋ ฌ๋ก ์คํํฉ๋๋ค. ํ์ ๊ฐ ํํฐ์ ์ UDTF์ ๋จ์ผ ์ธ์คํด์ค๋ก ์ ๋ฌ๋ฉ๋๋ค.
๊ฐ ํํฐ์ ์ ํ๋์ UDTF ์ธ์คํด์ค์์๋ง ์ฒ๋ฆฌ๋์ง๋ง, ๊ทธ ๋ฐ๋์ ๊ฒฝ์ฐ์๋ ๋ฐ๋์ ๊ทธ๋ฐ ๊ฒ์ ์๋๋๋ค. ์ฆ, ๋จ์ผ UDTF ์ธ์คํด์ค๋ ์ฌ๋ฌ ํํฐ์ ์ ์์ฐจ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ด๋์ ๋ผ์ด์ ์ ํ์ด๋๋ผ์ด์ ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ ํํฐ์ ์ ์ด๊ธฐํ ๋ฐ ์ ๋ฆฌํ์ฌ ํ ํํฐ์ ์ฒ๋ฆฌ์์ ๋ค๋ฅธ ํํฐ์ ์ฒ๋ฆฌ๋ก ๋์ ๊ฐ์ด ๋์ด๊ฐ์ง ์๋๋ก ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
์ฐธ๊ณ
ํ ์ด๋ธ ํ์ ํจ์(UDTF)์ ์ ๋ ฅ ์ธ์ 500๊ฐ, ์ถ๋ ฅ ์ด 500๊ฐ๋ก ์ ํ๋ฉ๋๋ค.
UDTFs์ฉ Java ํด๋์คยถ
UDTF์ ๊ธฐ๋ณธ ๊ตฌ์ฑ ์์๋ ํธ๋ค๋ฌ ํด๋์ค์ ์ถ๋ ฅ ํ ํด๋์ค์ ๋๋ค.
์ฒ๋ฆฌ๊ธฐ ํด๋์คยถ
Snowflake๋ ์ฃผ๋ก ํธ๋ค๋ฌ ํด๋์ค์ ๋ค์ ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ UDTF์ ์ํธ ์์ฉํฉ๋๋ค.
์ด๋์ ๋ผ์ด์ (์์ฑ์).
ํ๋ณ ๋ฉ์๋(
process
).ํ์ด๋๋ผ์ด์ ๋ฉ์๋(
endPartition
).
ํธ๋ค๋ฌ ํด๋์ค๋ ์ด ์ธ ๊ฐ์ง ๋ฉ์๋๋ฅผ ์ง์ํ๋ ๋ฐ ํ์ํ ์ถ๊ฐ ๋ฉ์๋๋ฅผ ํฌํจํ ์ ์์ต๋๋ค.
ํธ๋ค๋ฌ ํด๋์ค์๋ getOutputClass
๋ฉ์๋๋ ํฌํจ๋๋ฉฐ, ์ด๋ ๋์ค์ ์ค๋ช
ํฉ๋๋ค.
ํธ๋ค๋ฌ ํด๋์ค(๋๋ ์ถ๋ ฅ ํ ํด๋์ค)์ ๋ฉ์๋์์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ์ฒ๋ฆฌ๊ฐ ์ค์ง๋ฉ๋๋ค. UDTF๋ฅผ ํธ์ถํ ์ฟผ๋ฆฌ๋ ์ค๋ฅ ๋ฉ์์ง์ ํจ๊ป ์คํจํฉ๋๋ค.
์์ฑ์ยถ
ํธ๋ค๋ฌ ํด๋์ค๋ ์์ฑ์๋ฅผ ๊ฐ์ง ์ ์์ผ๋ฉฐ, ์ด๋ 0๊ฐ์ ์ธ์๋ฅผ ์ทจํด์ผ ํฉ๋๋ค.
์์ฑ์๋ process
ํธ์ถ ์ ์ ๊ฐ ํํฐ์
์ ๋ํด ํ ๋ฒ์ฉ ํธ์ถ๋ฉ๋๋ค.
์์ฑ์๋ ์ถ๋ ฅ ํ์ ์์ฑํ ์ ์์ต๋๋ค.
์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ ํํฐ์
์ ์ํ๋ฅผ ์ด๊ธฐํํฉ๋๋ค. ์ด ์ํ๋ process
๋ฐ endPartition
๋ฉ์๋์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์์ฑ์๋ ํ๋น ํ ๋ฒ์ด ์๋๋ผ ํํฐ์
๋น ํ ๋ฒ๋ง ์ํํด์ผ ํ๋ ์ฅ๊ธฐ ์คํ ์ด๊ธฐํ๋ฅผ ๋ฐฐ์นํ๊ธฐ์ ์ ์ ํ ์์น์ด๊ธฐ๋ ํฉ๋๋ค.
์์ฑ์๋ ์ ํ ์ฌํญ์ ๋๋ค.
process
๋ฉ์๋ยถ
process
๋ฉ์๋๋ ์
๋ ฅ ํํฐ์
์ ๊ฐ ํ์ ๋ํด ํ ๋ฒ์ฉ ํธ์ถ๋ฉ๋๋ค.
UDTF์ ์ ๋ฌ๋ ์ธ์๋ process
์ ์ ๋ฌ๋ฉ๋๋ค. ์ธ์ ๊ฐ์ SQL ๋ฐ์ดํฐ ํ์
์์ Java ๋ฐ์ดํฐ ํ์
์ผ๋ก ๋ณํ๋ฉ๋๋ค. (SQL ๋ฐ Java ๋ฐ์ดํฐ ํ์
๋งคํ์ ๋ํ ์์ธํ ๋ด์ฉ์ SQL-Java ๋ฐ์ดํฐ ํ์
๋งคํ ์น์
์ ์ฐธ์กฐํ์ญ์์ค.)
process
๋ฉ์๋์ ๋งค๊ฐ ๋ณ์ ์ด๋ฆ์ ์ ํจํ Java ์๋ณ์์ผ ์ ์์ต๋๋ค. ์ด๋ฆ์ CREATE FUNCTION
๋ฌธ์ ์ง์ ๋ ์ด๋ฆ๊ณผ ์ผ์นํ ํ์๊ฐ ์์ต๋๋ค.
ํด๋น process
๊ฐ ํธ์ถ๋ ๋๋ง๋ค 0๊ฐ, 1๊ฐ ๋๋ ์ฌ๋ฌ ํ์ ๋ฐํํ ์ ์์ต๋๋ค.
process
๋ฉ์๋๊ฐ ๋ฐํํ๋ ๋ฐ์ดํฐ ํ์
์ Stream<OutputRow>
์ฌ์ผ ํฉ๋๋ค. ์ฌ๊ธฐ์ Stream์ java.util.stream.Stream์ ์ ์๋๊ณ OutputRow
๋ ์ถ๋ ฅ ํ ํด๋์ค์ ์ด๋ฆ์
๋๋ค. ์๋ ์๋ Stream์ ํตํด ์
๋ ฅ์ ๋ฐํํ๋ ๊ฐ๋จํ process
๋ฉ์๋๋ฅผ ๋ณด์ฌ์ค๋๋ค.
import java.util.stream.Stream;
...
public Stream<OutputRow> process(String v) {
return Stream.of(new OutputRow(v));
}
...
process
๋ฉ์๋๊ฐ ์ค๋ธ์ ํธ์ ์ํ๋ฅผ ์ ์งํ๊ฑฐ๋ ์ฌ์ฉํ์ง ์๋ ๊ฒฝ์ฐ(์: ์ถ๋ ฅ์์ ์ ํํ ์
๋ ฅ ํ์ ๋จ์ํ ์ ์ธํ๋๋ก ๋ฉ์๋๊ฐ ์ค๊ณ๋ ๊ฒฝ์ฐ) ๋ฉ์๋๋ฅผ static
์ผ๋ก ์ ์ธํ ์ ์์ต๋๋ค. process
๋ฉ์๋๊ฐ static
์ด๊ณ ํธ๋ค๋ฌ ํด๋์ค์ ์์ฑ์ ๋๋ ๋น์ ์ endPartition
๋ฉ์๋๊ฐ ์๋ ๊ฒฝ์ฐ Snowflake๋ ํธ๋ค๋ฌ ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง ์๊ณ ๊ฐ ํ์ ์ ์ process
๋ฉ์๋์ ์ง์ ์ ๋ฌํฉ๋๋ค.
์
๋ ฅ ํ์ ๊ฑด๋๋ฐ๊ณ ๋ค์ ํ์ ์ฒ๋ฆฌํด์ผ ํ๋ ๊ฒฝ์ฐ(์: ์
๋ ฅ ํ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ ๊ฒฝ์ฐ) ๋น Stream
์ค๋ธ์ ํธ๋ฅผ ๋ฐํํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์๋์ process
๋ฉ์๋๋ number
๊ฐ ์์ ์ ์์ธ ํ๋ง ๋ฐํํฉ๋๋ค. number
๊ฐ ์์๊ฐ ์๋ ๊ฒฝ์ฐ ๋ฉ์๋๋ ํ์ฌ ํ์ ๊ฑด๋๋ฐ๊ณ ๋ค์ ํ์ ๊ณ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ๋น Stream
์ค๋ธ์ ํธ๋ฅผ ๋ฐํํฉ๋๋ค.
public Stream<OutputRow> process(int number) {
if (inputNumber < 1) {
return Stream.empty();
}
return Stream.of(new OutputRow(number));
}
process
๊ฐ null Stream์ ๋ฐํํ๋ฉด ์ฒ๋ฆฌ๊ฐ ์ค์ง๋ฉ๋๋ค. (null Stream์ด ๋ฐํ๋๋๋ผ๋ endPartition
๋ฉ์๋๋ ๊ณ์ ํธ์ถ๋ฉ๋๋ค.)
์ด ๋ฉ์๋๋ ํ์์ ๋๋ค.
endPartition
๋ฉ์๋ยถ
์ด ์ ํ์ ๋ฉ์๋๋ process
์์ ์ง๊ณ๋ ์ํ ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ์ถ๋ ฅ ํ์ ์์ฑํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด ๋ฉ์๋๋ ํด๋น ํํฐ์
์ ๋ชจ๋ ํ์ด process
์ ์ ๋ฌ๋ ํ ๊ฐ ํํฐ์
์ ๋ํด ํ ๋ฒ ํธ์ถ๋ฉ๋๋ค.
์ด ๋ฉ์๋๋ฅผ ํฌํจํ๋ฉด ๋ฐ์ดํฐ๊ฐ ๋ช ์์ ์ผ๋ก ๋๋ ์์์ ์ผ๋ก ๋ถํ ๋์๋์ง ์ฌ๋ถ์ ๊ด๊ณ์์ด ๊ฐ ํํฐ์ ์์ ํธ์ถ๋ฉ๋๋ค. ๋ฐ์ดํฐ๊ฐ ์๋ฏธ ์๊ฒ ๋ถํ ๋์ง ์์ผ๋ฉด ํ์ด๋๋ผ์ด์ ์ ์ถ๋ ฅ์ด ์๋ฏธ๊ฐ ์์ ์ ์์ต๋๋ค.
์ฐธ๊ณ
์ฌ์ฉ์๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ช ์์ ์ผ๋ก ๋ถํ ํ์ง ์์ผ๋ฉด Snowflake๋ ๋ฐ์ดํฐ๋ฅผ ์์์ ์ผ๋ก ๋ถํ ํฉ๋๋ค. ์์ธํ ๋ด์ฉ์ ํํฐ์ ์ ์ฐธ์กฐํ์ญ์์ค.
์ด ๋ฉ์๋๋ 0๊ฐ, 1๊ฐ ๋๋ ์ฌ๋ฌ ํ์ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
์ฐธ๊ณ
Snowflake๋ ์ฑ๊ณต์ ์ผ๋ก ์ฒ๋ฆฌํ๋๋ก ์๊ฐ ์ ํ์ด ์กฐ์ ๋ ๋ํ ํํฐ์
์ ์ง์ํ์ง๋ง, ํนํ ๋ํ ํํฐ์
์ผ๋ก ์ธํด ์ฒ๋ฆฌ ์๊ฐ์ด ์ด๊ณผ๋ ์ ์์ต๋๋ค(์: endPartition
์ด ์๋ฃํ๋ ๋ฐ ๋๋ฌด ์ค๋ ๊ฑธ๋ฆฌ๋ ๊ฒฝ์ฐ). ํน์ ์ฌ์ฉ ์๋๋ฆฌ์ค์ ๋ง๊ฒ ์๊ฐ ์ด๊ณผ ์๊ณ๊ฐ์ ์กฐ์ ํด์ผ ํ๋ ๊ฒฝ์ฐ Snowflake ์ง์ ์ ๋ฌธ์ํ์ญ์์ค.
getOutputClass
๋ฉ์๋ยถ
์ด ๋ฉ์๋๋ ์ถ๋ ฅ ํ ํด๋์ค ์ ๋ํ ์ ๋ณด๋ฅผ ๋ฐํํฉ๋๋ค. ์ถ๋ ฅ ํ ํด๋์ค์๋ ๋ฐํ๋ ํ์ ๋ฐ์ดํฐ ํ์ ์ ๋ํ ์ ๋ณด๊ฐ ํฌํจ๋ฉ๋๋ค.
์ถ๋ ฅ ํ ํด๋์คยถ
Snowflake๋ ์ถ๋ ฅ ํ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ Java ๋ฐ์ดํฐ ํ์ ๊ณผ SQL ๋ฐ์ดํฐ ํ์ ๊ฐ์ ๋ณํ์ ์ง์ ํ๋ ๋ฐ ๋์์ ์ค๋๋ค.
Java UDTF๊ฐ ํ์ ๋ฐํํ ๋ ํ์ ๊ฐ ์ด์ ์๋ ๊ฐ์ Java ๋ฐ์ดํฐ ํ์
์์ ํด๋น SQL ๋ฐ์ดํฐ ํ์
์ผ๋ก ๋ณํ๋์ด์ผ ํฉ๋๋ค. SQL ๋ฐ์ดํฐ ํ์
์ CREATE FUNCTION
๋ฌธ์ RETURNS
์ ์ ์ง์ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ Java ๋ฐ SQL ๋ฐ์ดํฐ ํ์
๊ฐ์ ๋งคํ์ 1:1์ด ์๋๋ฏ๋ก Snowflake๋ ๋ฐํ๋ ๊ฐ ์ด์ ๋ํ Java ๋ฐ์ดํฐ ํ์
์ ์์์ผ ํฉ๋๋ค. (SQL ๋ฐ Java ๋ฐ์ดํฐ ํ์
๋งคํ์ ๋ํ ์์ธํ ๋ด์ฉ์ SQL-Java ๋ฐ์ดํฐ ํ์
๋งคํ ์น์
์ ์ฐธ์กฐํ์ญ์์ค.)
Java UDTF๋ ์ถ๋ ฅ ํ ํด๋์ค๋ฅผ ์ ์ํ์ฌ ์ถ๋ ฅ ์ด์ Java ๋ฐ์ดํฐ ํ์ ์ ์ง์ ํฉ๋๋ค. UDTF์์ ๋ฐํ๋ ๊ฐ ํ์ ์ถ๋ ฅ ํ ํด๋์ค์ ์ธ์คํด์ค๋ก ๋ฐํ๋ฉ๋๋ค. ์ถ๋ ฅ ํ ํด๋์ค์ ๊ฐ ์ธ์คํด์ค์๋ ๊ฐ ์ถ๋ ฅ ์ด์ ๋ํด ํ๋์ ๊ณต์ฉ ํ๋๊ฐ ์์ต๋๋ค. Snowflake๋ ์ถ๋ ฅ ํ ํด๋์ค์ ๊ฐ ์ธ์คํด์ค์์ ๊ณต์ฉ ํ๋ ๊ฐ์ ์ฝ๊ณ , Java ๊ฐ์ SQL ๊ฐ์ผ๋ก ๋ณํํ๊ณ , ํด๋น ๊ฐ์ ํฌํจํ๋ SQL ์ถ๋ ฅ ํ์ ๊ตฌ์ฑํฉ๋๋ค.
์ถ๋ ฅ ํ ํด๋์ค์ ๊ฐ ์ธ์คํด์ค์ ์๋ ๊ฐ์ ์ถ๋ ฅ ํ ํด๋์ค์ ์์ฑ์๋ฅผ ํธ์ถํ์ฌ ์ค์ ๋ฉ๋๋ค. ์์ฑ์๋ ์ถ๋ ฅ ์ด์ ํด๋นํ๋ ๋งค๊ฐ ๋ณ์๋ฅผ ์๋ฝํ ๋ค์ ๊ณต์ฉ ํ๋๋ฅผ ํด๋น ๋งค๊ฐ ๋ณ์๋ก ์ค์ ํฉ๋๋ค.
์๋ ์ฝ๋๋ ์ํ ์ถ๋ ฅ ํ ํด๋์ค๋ฅผ ์ ์ํฉ๋๋ค.
class OutputRow {
public String name;
public int id;
public OutputRow(String pName, int pId) {
this.name = pName;
this.id = pId;
}
}
์ด ํด๋์ค์ ์ํด ์ง์ ๋ ๊ณต์ฉ ๋ณ์๋ CREATE FUNCTION
๋ฌธ์ RETURNS TABLE (...)
์ ์ ์ง์ ๋ ์ด๊ณผ ์ผ์นํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์์ OutputRow
ํด๋์ค๋ ์๋์ RETURNS
์ ์ ํด๋นํฉ๋๋ค.
CREATE FUNCTION F(...)
RETURNS TABLE(NAME VARCHAR, ID INTEGER)
...
์ค์
SQL ์ด ์ด๋ฆ๊ณผ ์ถ๋ ฅ ํ ํด๋์ค์ Java ๊ณต์ฉ ํ๋ ์ด๋ฆ ๊ฐ์ ์ผ์น๋ ๋/์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์์ ํ์๋ Java ๋ฐ SQL ์ฝ๋์์ id
๋ผ๋ Java ํ๋๋ ID
๋ผ๋ SQL ์ด์ ํด๋นํฉ๋๋ค.
์ถ๋ ฅ ํ ํด๋์ค๋ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉ๋ฉ๋๋ค.
ํธ๋ค๋ฌ ํด๋์ค๋ ์ถ๋ ฅ ํ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ
process
๋ฉ์๋์endPartition
๋ฉ์๋์ ๋ฐํ ํ์ ์ ์ง์ ํฉ๋๋ค. ํธ๋ค๋ฌ ํด๋์ค๋ ๋ํ ์ถ๋ ฅ ํ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐํ๋ ๊ฐ์ ๊ตฌ์ฑํฉ๋๋ค. ์:public Stream<OutputRow> process(String v) { ... return Stream.of(new OutputRow(...)); } public Stream<OutputRow> endPartition() { ... return Stream.of(new OutputRow(...)); }
์ถ๋ ฅ ํ ํด๋์ค๋ ํธ๋ค๋ฌ ํด๋์ค์
getOutputClass
๋ฉ์๋์์๋ ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ Snowflake๊ฐ ์ถ๋ ฅ์ Java ๋ฐ์ดํฐ ํ์ ์ ํ์ตํ๊ธฐ ์ํด ํธ์ถํ๋ ์ ์ ๋ฉ์๋์ ๋๋ค.public static Class getOutputClass() { return OutputRow.class; }
์ถ๋ ฅ ํ ํด๋์ค(๋๋ ์ฒ๋ฆฌ๊ธฐ ํด๋์ค)์ ๋ฉ์๋์์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ์ฒ๋ฆฌ๊ฐ ์ค์ง๋ฉ๋๋ค. UDTF๋ฅผ ํธ์ถํ ์ฟผ๋ฆฌ๋ ์ค๋ฅ ๋ฉ์์ง์ ํจ๊ป ์คํจํฉ๋๋ค.
์๊ตฌ ์ฌํญ ์์ฝยถ
UDTF์ Java ์ฝ๋๋ ๋ค์ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํด์ผ ํฉ๋๋ค.
์ฝ๋๋ ์ถ๋ ฅ ํ ํด๋์ค ๋ฅผ ์ ์ํด์ผ ํฉ๋๋ค.
UDTF ํธ๋ค๋ฌ ํด๋์ค์๋
<์ถ๋ ฅ_ํ_ํด๋์ค>
์ Stream์ ๋ฐํํ๋process
๋ผ๋ ๊ณต์ฉ ๋ฉ์๋๊ฐ ํฌํจ๋์ด์ผ ํฉ๋๋ค. ์ฌ๊ธฐ์ Stream์ java.util.stream.Stream์ ์ ์๋์ด ์์ต๋๋ค.UDTF ํธ๋ค๋ฌ ํด๋์ค๋
<์ถ๋ ฅ_ํ_ํด๋์ค>.class
๋ฅผ ๋ฐํํด์ผ ํ๋getOutputClass
๋ผ๋ ๊ณต์ฉ ์ ์ ๋ฉ์๋๋ฅผ ์ ์ํด์ผ ํฉ๋๋ค.
Java ์ฝ๋๊ฐ ์ด๋ฌํ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ์ง ์์ผ๋ฉด UDTF ์์ฑ ๋๋ ์คํ์ด ์คํจํฉ๋๋ค.
CREATE FUNCTION ๋ฌธ์ด ์คํ๋ ๋ ์ธ์ ์ ํ์ฑ ์จ์ดํ์ฐ์ค๊ฐ ์๋ ๊ฒฝ์ฐ Snowflake๋ ํจ์๊ฐ ์์ฑ๋ ๋ ์๋ฐ์ ๊ฐ์งํฉ๋๋ค.
CREATE FUNCTION ๋ฌธ์ด ์คํ๋ ๋ ์ธ์ ์ ํ์ฑ ์จ์ดํ์ฐ์ค๊ฐ ์์ผ๋ฉด Snowflake๋ ํจ์๊ฐ ํธ์ถ๋ ๋ ์๋ฐ์ ๊ฐ์งํฉ๋๋ค.
์ฟผ๋ฆฌ์์ Java UDTFs ํธ์ถ์ ์ยถ
UDF ๋ฐ UDTF ํธ์ถ์ ๋ํ ์ผ๋ฐ ์ ๋ณด๋ UDF ์คํํ๊ธฐ ์น์ ์ ์ฐธ์กฐํ์ญ์์ค.
๋ช ์์ ๋ถํ ์์ด ํธ์ถํ๊ธฐยถ
์ด ์๋ UDTF๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. ์ด ์๋ ๊ฐ ์ ๋ ฅ์ ๋ ๋ณต์ฌ๋ณธ์ ๋ฐํํ๊ณ ๊ฐ ํํฐ์ ์ ๋ํด ํ๋์ ์ถ๊ฐ ํ์ ๋ฐํํฉ๋๋ค.
create function return_two_copies(v varchar)
returns table(output_value varchar)
language java
handler='TestFunction'
target_path='@~/TestFunction.jar'
as
$$
import java.util.stream.Stream;
class OutputRow {
public String output_value;
public OutputRow(String outputValue) {
this.output_value = outputValue;
}
}
class TestFunction {
String myString;
public TestFunction() {
myString = "Created in constructor and output from endPartition()";
}
public static Class getOutputClass() {
return OutputRow.class;
}
public Stream<OutputRow> process(String inputValue) {
// Return two rows with the same value.
return Stream.of(new OutputRow(inputValue), new OutputRow(inputValue));
}
public Stream<OutputRow> endPartition() {
// Returns the value we initialized in the constructor.
return Stream.of(new OutputRow(myString));
}
}
$$;
์ด ์๋ UDTF๋ฅผ ํธ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. ์ด ์๋ฅผ ๋จ์ํ๊ฒ ์ ์งํ๊ธฐ ์ํด ๋ฌธ์ ์ด์ด ์๋ ๋ฆฌํฐ๋ด ๊ฐ์ ์ ๋ฌํ๊ณ OVER()
์ ์ ์๋ตํฉ๋๋ค.
SELECT output_value
FROM TABLE(return_two_copies('Input string'));
+-------------------------------------------------------+
| OUTPUT_VALUE |
|-------------------------------------------------------|
| Input string |
| Input string |
| Created in constructor and output from endPartition() |
+-------------------------------------------------------+
์ด ์์์๋ ๋ค๋ฅธ ํ
์ด๋ธ์ ์ฝ์ ๊ฐ์ผ๋ก UDTF๋ฅผ ํธ์ถํฉ๋๋ค. process
๋ฉ์๋๊ฐ ํธ์ถ๋ ๋๋ง๋ค cities_of_interest
ํ
์ด๋ธ์ ํ์ฌ ํ์ ์๋ city_name
์ด์ ๊ฐ์ด ์ ๋ฌ๋ฉ๋๋ค. ์์ ๊ฐ์ด, UDTF๋ ๋ช
์์ OVER()
์ ์์ด ํธ์ถ๋ฉ๋๋ค.
์ ๋ ฅ ์์ค๋ก ์ฌ์ฉํ ๊ฐ๋จํ ํ ์ด๋ธ์ ๋ง๋ญ๋๋ค.
CREATE TABLE cities_of_interest (city_name VARCHAR);
INSERT INTO cities_of_interest (city_name) VALUES
('Toronto'),
('Warsaw'),
('Kyoto');
Java UDTF ํธ์ถ:
SELECT city_name, output_value
FROM cities_of_interest,
TABLE(return_two_copies(city_name))
ORDER BY city_name, output_value;
+-----------+-------------------------------------------------------+
| CITY_NAME | OUTPUT_VALUE |
|-----------+-------------------------------------------------------|
| Kyoto | Kyoto |
| Kyoto | Kyoto |
| Toronto | Toronto |
| Toronto | Toronto |
| Warsaw | Warsaw |
| Warsaw | Warsaw |
| NULL | Created in constructor and output from endPartition() |
+-----------+-------------------------------------------------------+
์ฃผ์
์ด ์์์ FROM ์ ์ ์ฌ์ฉ๋ ๊ตฌ๋ฌธ์ ๋ด๋ถ ์กฐ์ธ์ ๊ตฌ๋ฌธ(์ฆ, FROM t1, t2
)๊ณผ ๋์ผํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ํ๋ ์์
์ ์ค์ ๋ด๋ถ ์กฐ์ธ์ด ์๋๋๋ค. ์ค์ ๋์์ ํจ์๊ฐ ํ
์ด๋ธ์ ์๋ ๊ฐ ํ์ ๊ฐ์ผ๋ก ํธ์ถ๋๋ค๋ ๊ฒ์
๋๋ค. ์ฆ, ๋ค์ FROM ์ ์ด ์ฃผ์ด์ก์ ๋:
FROM cities_of_interest, TABLE(f(city_name))
๋์์ ๋ค์ ์์ฌ ์ฝ๋์ ๋์ผํฉ๋๋ค.
for city_name in cities_of_interest:
output_row = f(city_name)
JavaScript UDTF์ ๋ํ ์ค๋ช ์์ ์ ์น์ ์๋ ํ ์ด๋ธ์ ๊ฐ์ผ๋ก UDTF๋ฅผ ํธ์ถํ๋ ์ฟผ๋ฆฌ์ ๋ ๋ณต์กํ ์๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
์ด ๋ฌธ์ด ๋ถํ ์ ๋ช ์์ ์ผ๋ก ์ง์ ํ์ง ์์ ๊ฒฝ์ฐ์๋ Snowflake ์คํ ์์ง์ ์์์ ๋ถํ ์ ์ฌ์ฉํฉ๋๋ค.
ํํฐ์
์ด ํ๋๋ง ์๋ ๊ฒฝ์ฐ endPartition
๋ฉ์๋๋ ํ ๋ฒ๋ง ํธ์ถ๋๊ณ ์ฟผ๋ฆฌ ์ถ๋ ฅ์๋ Created in constructor and output from endPartition()
๊ฐ์ด ์๋ ํ์ด ํ๋๋ง ํฌํจ๋ฉ๋๋ค. ๋ฌธ์ ๋ค๋ฅด๊ฒ ์คํํ๋ ์ค์ ๋ฐ์ดํฐ๊ฐ ๋ค๋ฅธ ๊ฐ์์ ํํฐ์
์ผ๋ก ๊ทธ๋ฃนํ๋๋ฉด endPartition
๋ฉ์๋๊ฐ ๋ค๋ฅธ ํ์๋ก ํธ์ถ๋๊ณ ์ถ๋ ฅ์๋ ์ด ํ์ ๋ณต์ฌ๋ณธ์ด ํฌํจ๋๋๋ฐ ๊ทธ ๊ฐ์๊ฐ ๋ค๋ฆ
๋๋ค.
์์ธํ ๋ด์ฉ์ ์์์ ๋ถํ ์ ์ฐธ์กฐํ์ญ์์ค.
๋ช ์์ ๋ถํ ๋ก ํธ์ถํ๊ธฐยถ
Java UDTF๋ ๋ช ์์ ๋ถํ ์ ์ฌ์ฉํ์ฌ ํธ์ถํ ์๋ ์์ต๋๋ค.
๋ค์ค ํํฐ์ ยถ
๋ค์ ์์์๋ ์ด์ ์ ๋ง๋ ๋์ผํ UDTF ๋ฐ ํ ์ด๋ธ์ ์ฌ์ฉํฉ๋๋ค. ์ด ์์์๋ city_name์ ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ถํ ํฉ๋๋ค.
SELECT city_name, output_value
FROM cities_of_interest,
TABLE(return_two_copies(city_name) OVER (PARTITION BY city_name))
ORDER BY city_name, output_value;
+-----------+-------------------------------------------------------+
| CITY_NAME | OUTPUT_VALUE |
|-----------+-------------------------------------------------------|
| Kyoto | Created in constructor and output from endPartition() |
| Kyoto | Kyoto |
| Kyoto | Kyoto |
| Toronto | Created in constructor and output from endPartition() |
| Toronto | Toronto |
| Toronto | Toronto |
| Warsaw | Created in constructor and output from endPartition() |
| Warsaw | Warsaw |
| Warsaw | Warsaw |
+-----------+-------------------------------------------------------+
๋จ์ผ ํํฐ์ ยถ
๋ค์ ์์์๋ ์ด์ ์ ๋ง๋ ๋์ผํ UDTF ๋ฐ ํ ์ด๋ธ์ ์ฌ์ฉํ๊ณ , ์์๋ก ๋ฐ์ดํฐ๋ฅผ ๋ถํ ํ๋ฏ๋ก Snowflake๋ ๋จ์ผ ๋ถํ ๋ง ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค.
SELECT city_name, output_value
FROM cities_of_interest,
TABLE(return_two_copies(city_name) OVER (PARTITION BY 1))
ORDER BY city_name, output_value;
+-----------+-------------------------------------------------------+
| CITY_NAME | OUTPUT_VALUE |
|-----------+-------------------------------------------------------|
| Kyoto | Kyoto |
| Kyoto | Kyoto |
| Toronto | Toronto |
| Toronto | Toronto |
| Warsaw | Warsaw |
| Warsaw | Warsaw |
| NULL | Created in constructor and output from endPartition() |
+-----------+-------------------------------------------------------+
๋ฉ์์ง Created in constructor and output from endPartition()
์ ๋ณต์ฌ๋ณธ ํ๋๋ง ์ถ๋ ฅ์ ํฌํจ๋์์ผ๋ฉฐ ์ด๋ endPartition
์ด ํ ๋ฒ๋ง ํธ์ถ๋์์์ ๋ํ๋
๋๋ค.
๋งค์ฐ ํฐ ์ ๋ ฅ(์: ํฐ ํ์ผ) ์ฒ๋ฆฌํ๊ธฐยถ
์ด๋ค ๊ฒฝ์ฐ์๋ UDTF๊ฐ ๊ฐ ์ ๋ ฅ ํ์ ์ฒ๋ฆฌํ๋ ๋ฐ ๋งค์ฐ ๋ง์ ์์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, UDTF๋ ๋๋ฌด ์ปค์ ๋ฉ๋ชจ๋ฆฌ์ ๋ง์ง ์๋ ํ์ผ์ ์ฝ๊ณ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
UDF ๋๋ UDTF์ ๋์ฉ๋ ํ์ผ์ ์ฒ๋ฆฌํ๋ ค๋ฉด SnowflakeFile
ํด๋์ค ๋๋ InputStream
ํด๋์ค๋ฅผ ์ฌ์ฉํ์ญ์์ค. ์์ธํ ๋ด์ฉ์ UDF ๋ฐ ํ๋ก์์ ์ฒ๋ฆฌ๊ธฐ๋ก ๋น์ ํ ๋ฐ์ดํฐ ์ฒ๋ฆฌํ๊ธฐ ์น์
์ ์ฐธ์กฐํ์ญ์์ค.