์Šค์นผ๋ผ Scala UDFs์—์„œ ์ „์—ญ ์ƒํƒœ ์ œ์–ดํ•˜๊ธฐยถ

๊ณต์œ  ์ƒํƒœ์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๊ฐ€ ํ•„์š”ํ•œ UDF์™€ ์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์„ค๊ณ„ํ•  ๋•Œ Snowflake๊ฐ€ UDF๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ํ–‰์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์„ ์„ค๋ช…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ์ฒ˜๋ฆฌ๊ธฐ๋Š” ๋‹ค์Œ ์ง€์นจ์„ ๋”ฐ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ํ–‰ ๊ฐ„์— ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๊ณต์œ  ์ƒํƒœ๋ฅผ ์ดˆ๊ธฐํ™”ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ๊ธฐ ํ•จ์ˆ˜ ์™ธ๋ถ€์—์„œ(์˜ˆ: ์ƒ์„ฑ์ž์—์„œ) ์ดˆ๊ธฐํ™”ํ•˜์‹ญ์‹œ์˜ค.

  • ์Šค๋ ˆ๋“œ๋กœ๋ถ€ํ„ฐ ์•ˆ์ „ํ•˜๋„๋ก ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜์‹ญ์‹œ์˜ค.

  • ํ–‰ ๊ฐ„์— ๋™์  ์ƒํƒœ๋ฅผ ์ €์žฅ ๋ฐ ๊ณต์œ ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

UDF๊ฐ€ ์ด๋Ÿฌํ•œ ์ง€์นจ์„ ๋”ฐ๋ฅผ ์ˆ˜ ์—†๊ฑฐ๋‚˜ ์ด๋Ÿฌํ•œ ์ง€์นจ์˜ ์ด์œ ๋ฅผ ๋” ๊นŠ์ด ์ดํ•ดํ•˜๋ ค๋Š” ๊ฒฝ์šฐ, ๋‹ค์Œ ๋ช‡ ๊ฐ€์ง€ ํ•˜์œ„ ์„น์…˜์„ ์ฝ์œผ์‹ญ์‹œ์˜ค.

ํ˜ธ์ถœ ๊ฐ„ ์ƒํƒœ ๊ณต์œ ํ•˜๊ธฐยถ

Snowflake๋Š” ์Šค์นผ๋ผ UDF๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•ฉ๋‹ˆ๋‹ค. ํ˜ธ์ถœ ๊ฐ„์— ๊ณต์œ ๋˜๋Š” ์ƒํƒœ์— ์˜์กดํ•˜๋ฉด ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๋™์ž‘์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์‹œ์Šคํ…œ์—์„œ ํ–‰์„ ์ž„์˜์˜ ์ˆœ์„œ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ์—ฌ๋Ÿฌ JVM(Java ๋˜๋Š” Scala๋กœ ์ž‘์„ฑ๋œ ์ฒ˜๋ฆฌ๊ธฐ์˜ ๊ฒฝ์šฐ)์— ๊ฑธ์ณ ์ด๋Ÿฌํ•œ ํ˜ธ์ถœ์„ ๋ถ„์‚ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

UDF๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ํ˜ธ์ถœ์—์„œ ๊ณต์œ  ์ƒํƒœ์— ์˜์กดํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ UDF์—์„œ ๊ณต์œ  ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋ ค ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์Œ ๋‘ ๊ฐ€์ง€ ์ƒํ™ฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๊ฐ ํ–‰์— ๋Œ€ํ•ด ๋ฐ˜๋ณตํ•˜๊ณ  ์‹ถ์ง€ ์•Š์€, ๋ถ€๋‹ด์ด ํฐ ์ดˆ๊ธฐํ™” ๋…ผ๋ฆฌ๊ฐ€ ํฌํ•จ๋œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

  • ์บ์‹œ์™€ ๊ฐ™์ด ํ–‰ ๊ฐ„์— ๊ณต์œ  ์ƒํƒœ๋ฅผ ํ™œ์šฉํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ํ–‰์—์„œ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•ด์•ผ ํ•˜๊ณ  ํ•ด๋‹น ์ƒํƒœ๊ฐ€ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋„ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ, ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ธ์Šคํ„ด์Šค ์ˆ˜์ค€ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•ด ๊ณต์œ  ์ƒํƒœ๋ฅผ ๋งŒ๋“œ์‹ญ์‹œ์˜ค. ์ƒ์„ฑ์ž๋Š” ์ธ์Šคํ„ด์Šค๋‹น ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋Š” ๋ฐ˜๋ฉด ํ•ธ๋“ค๋Ÿฌ๋Š” ํ–‰๋‹น ํ•œ ๋ฒˆ ํ˜ธ์ถœ๋˜๋ฏ€๋กœ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์—ฌ๋Ÿฌ ํ–‰์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ์ƒ์„ฑ์ž์—์„œ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๊ฒƒ์ด ๋ถ€๋‹ด์ด ๋” ์ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ƒ์„ฑ์ž๋Š” ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์„ฑ์ž๋Š” ์Šค๋ ˆ๋“œ๋กœ๋ถ€ํ„ฐ ์•ˆ์ „ํ•˜๋„๋ก ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋ณ€๊ฒฝ๋˜๋Š” ๊ณต์œ  ์ƒํƒœ๋ฅผ UDF๊ฐ€ ์ €์žฅํ•˜๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น ์ƒํƒœ์— ๋Œ€ํ•œ ๋™์‹œ ์•ก์„ธ์Šค๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ค€๋น„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ๋ฐ ๊ณต์œ  ์ƒํƒœ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ด ํ•ญ๋ชฉ์˜ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์ดํ•ดํ•˜๊ธฐ ๋ฐ JVM ์ƒํƒœ ์ •๋ณด ์ €์žฅํ•˜๊ธฐ ์„น์…˜์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์ดํ•ดํ•˜๊ธฐยถ

์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด Snowflake๋Š” JVM ์ „์ฒด์— ๊ฑธ์ณ, ๊ทธ๋ฆฌ๊ณ  JVM ๋‚ด์—์„œ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.

JVMs ์ „์ฒด์— ๊ฑธ์ณ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•˜๊ธฐยถ

Snowflake๋Š” ์›จ์–ดํ•˜์šฐ์Šค ์˜ ์ž‘์—…์ž ์ „์ฒด์— ๊ฑธ์ณ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ž‘์—…์ž๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ JVM์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ „์—ญ ๊ณต์œ  ์ƒํƒœ๊ฐ€ ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๊ปํ•ด์•ผ ๋‹จ์ผ JVM ๋‚ด์—์„œ๋งŒ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

JVMs ๋‚ด์—์„œ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•˜๊ธฐยถ

  • ๊ฐ JVM์€ ๋™์ผํ•œ ์ธ์Šคํ„ด์Šค์˜ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ๋ณ‘๋ ฌ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๊ฐ€ ์Šค๋ ˆ๋“œ๋กœ๋ถ€ํ„ฐ ์•ˆ์ „ํ•ด์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

  • UDF๊ฐ€ IMMUTABLE์ด๊ณ  SQL ๋ฌธ์ด ๋™์ผ ํ–‰์— ๋Œ€ํ•ด ๋™์ผ ์ธ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ UDF๋ฅผ ๋‘ ๋ฒˆ ์ด์ƒ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ, UDF๋Š” ํ•ด๋‹น ํ–‰์˜ ๊ฐ ํ˜ธ์ถœ์— ๋Œ€ํ•ด ๋™์ผ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

    ์˜ˆ๋ฅผ ๋“ค์–ด, UDF๊ฐ€ IMMUTABLE์ธ ๊ฒฝ์šฐ ๋‹ค์Œ์€ ๊ฐ ํ–‰์— ๋Œ€ํ•ด ๋™์ผ ๊ฐ’์„ ๋‘ ๋ฒˆ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

    SELECT my_scala_udf(42), my_scala_udf(42) FROM table1;
    
    Copy

    ๋™์ผ ์ธ์ž๊ฐ€ ์ „๋‹ฌ๋œ ๊ฒฝ์šฐ์—๋„ ์—ฌ๋Ÿฌ ํ˜ธ์ถœ์ด ๋…๋ฆฝ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ํ•จ์ˆ˜ VOLATILE์„ ์„ ์–ธํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด ์—ฌ๋Ÿฌ ๊ฐœ๋ณ„ UDF๋ฅผ ๋™์ผ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์— ๋ฐ”์ธ๋”ฉํ•˜์‹ญ์‹œ์˜ค.

    ๋‹ค์Œ ๋‹จ๊ณ„์— ๋”ฐ๋ผ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    1. ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ @udf_libs/rand.jar ๋ผ๋Š” JAR ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

      class MyClass {
      
        var x: Double = 0.0
      
        // Constructor
        def this() = {
          x = Math.random()
        }
      
        // Handler
        def myHandler(): Double = x
      }
      
      Copy
    2. ์•„๋ž˜์™€ ๊ฐ™์ด Scala UDF๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

      ์ด๋Ÿฌํ•œ UDF๋Š” ์ด๋ฆ„์ด ๋‹ค๋ฅด์ง€๋งŒ, ๋™์ผ JAR ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ํ•ด๋‹น JAR ํŒŒ์ผ ๋‚ด์—์„œ ๋™์ผ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

      CREATE FUNCTION my_scala_udf_1()
        RETURNS DOUBLE
        LANGUAGE SCALA
        IMPORTS = ('@udf_libs/rand.jar')
        HANDLER = 'MyClass.myHandler';
      
      CREATE FUNCTION my_scala_udf_2()
        RETURNS DOUBLE
        LANGUAGE SCALA
        IMPORTS = ('@udf_libs/rand.jar')
        HANDLER = 'MyClass.myHandler';
      
      Copy
    3. ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‘ UDF๋ฅผ ๋ชจ๋‘ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

      UDF๋Š” ๋™์ผํ•œ JAR ํŒŒ์ผ ๋ฐ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ˜ธ์ถœ์€ ๋™์ผํ•œ ํด๋ž˜์Šค์˜ ๋‘ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ฐ ์ธ์Šคํ„ด์Šค๋Š” ๋…๋ฆฝ์ ์ธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ์•„๋ž˜ ์˜ˆ์—์„œ๋Š” ๋™์ผ ๊ฐ’์„ ๋‘ ๋ฒˆ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋Œ€์‹  ๋‘ ๊ฐœ์˜ ๋…๋ฆฝ์ ์ธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

      SELECT my_scala_udf_1(), my_scala_udf_2() FROM table1;
      
      Copy

JVM ์ƒํƒœ ์ •๋ณด ์ €์žฅํ•˜๊ธฐยถ

๋™์  ๊ณต์œ  ์ƒํƒœ์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ํ•œ ๊ฐ€์ง€ ์ด์œ ๋Š” ํ–‰์ด ๋ฐ˜๋“œ์‹œ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์ˆœ์„œ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. SQL ๋ฌธ์ด ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค Snowflake๋Š” ๋ฐฐ์น˜ ์ˆ˜, ๋ฐฐ์น˜๊ฐ€ ์ฒ˜๋ฆฌ๋˜๋Š” ์ˆœ์„œ, ๋ฐฐ์น˜ ๋‚ด์˜ ํ–‰ ์ˆœ์„œ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ ํ–‰์ด ํ›„์† ํ–‰์˜ ๋ฐ˜ํ™˜ ๊ฐ’์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋„๋ก ์Šค์นผ๋ผ UDF๊ฐ€ ์„ค๊ณ„๋œ ๊ฒฝ์šฐ, UDF๋Š” UDF๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.