Problem:

Przeprowadzasz audyt istniejącego rozwiązania zbudowanego w oparciu o Databricks i Sparka.
Dla potrzeb budowy nowego modułu potrzebujesz sprawdzić, gdzie w widokach jest odwołanie do tabeli, którą będziesz zmieniał. Masz nieodparte wrażenie, że development został wykonany w sposób niechlujny i w notebookach nie ma wszystkiego. Część została zrobiona i potem zapomniana.
Potrzebujesz wydobyć definicję tabel i widoków zapisaną w hive metastore.

Rozwiązanie:

Użyj polecenia

SHOW CREATE TABLE

Generuje ono skrypt SQL z definicją tabeli lub widoku.
Potrzeba trochę ulepszyć tą metodę. Ona zwraca definicję dla jednej tabeli i widoku. W naszej bazie jest tych tabel i widoków 100+.
Wykorzystamy SHOW VIEWS i SHOW TABLE i zautomatyzujemy sobie pracę. Na koniec zapiszemy wszystko do tabeli.

Definiowanie zmiennych i import modułów

Zacznijmy od zdefiniowania parametrów i przypiszemy im domyślne wartości. Definiowanie parametrów to dla mnie dobra praktyka. Dzięki temu łatwiej przeniesiesz notebook na inne środowisko.

dbutils.widgets.text('db_name','next_level_dm')
dbutils.widgets.text('user_table_def_name','dbx_user_tab_def')

Będziemy jeszcze potrzebowali zaimportować moduły z pythona:

from pyspark.sql.functions import lit
from datetime import datetime

Pierwszy będzie używany do wstawienia kolumny do data frame, drugi do wygenerowania bierzącej daty.

Pobieranie definicji tabel i widoków

Spark posiada dwie możliwości na porbranie definicji widoków:

  • Show views
  • Show tables

Show views wybiera tylko widoki, natomiast show tables wybiera tabele i widoki. Dlatego, wybierzemy polecenie show view. Dzięki temu dostaniemy tylko widoki. Potem wstawimy do tabeli z metadanymi informację jaki to typ obiektu

def user_view_definitions(db_name: str):
    df_views = spark.sql(f"show views in {db_name}" )
    user_view_def = None
    for row in df_views.collect():
        df_view = spark.sql(f"show create table {db_name}.{row.viewName}" )
        df_view = df_view.withColumn('database_name',lit(db_name)).withColumn('table_name',lit(row.viewName)).withColumn('type',lit('view'))
        user_view_def = df_view.alias('user_view_def') if user_view_def is None else user_view_def.unionAll(df_view)
    return user_view_def

Teraz chcemy do definicji widoków dodać jeszcze definicję tabel. Chcemy również odfiltrować definicję widoków, które mamy już w data frame. Dlatego jako jeden z parametrów do fukncji podamy listę widoków, których definicję już posiadamy.

def user_tab_definitions(db_name: str, view_list: []):
    df_tables = spark.sql(f"show tables in {db_name}")
    user_tab_def = None
    for row in df_tables.collect():
        #filter out views
        if row.tableName not in view_list:
            df_table = spark.sql(f"show create table {db_name}.{row.tableName}")
            df_table = df_table.withColumn('database_name',lit(db_name)).withColumn('table_name',lit(row.tableName)).withColumn('type',lit('table'))
            user_tab_def = df_table.alias('user_tab_def') if user_tab_def is None else user_tab_def.unionAll(df_table)
    return user_tab_def

Zostało scalić dane razem i zapisać do tabeli.

O czym warto pamiętać

Show tables - zwraca zarówno definicję widoków jak i tabel. W show tables nie możesz łatwo rozróżnić co jest widokiem a co tabelą, dlatego z pomocą przychodzi show view zawierające tylko definicję widoków.

Definicja widoków jest typu string, dlatego łatwo ją przeszukiwać.

Problem z pierwszego paragrafu jest zaadresowany ale jeszcze nie rozwiązany. Co jeszcze, można zrobić, żeby sprawdzić czy w notebookach jest wszystko co potrzeba i nie brakuje żadnego obiektu?

Na przykład można stworzyć nową bazę i tam zrobić deployment. Ewentualnie, ale bardziej ryzykownie możesz utworzyć sobie definicję widoków i tabel a potem usunąć wszystkie tabele i widoki, dla których stworzyłeś definicję. Dlaczego to ryzykowne? Ponieważ tracisz przy tym wszystkie dane. Zakładając, że pracujesz na środowisku developerskim zapewne możesz to zrobić ale pamiętaj o komunikacji z zespołem. Benefitem będzie uzyskanie większej pewności do kodu, którzy przyszło Ci wspierać.