Problem:

Jaki jest rozmiar tabeli w Databricks? Ile miejsca zajmuje mój schemat? Jak policzyć rozmiar? W jaki sposób sprawdzić ile przybyło danych od ostatniego ładowania? Ile miejsca zajmuje bronze, silver oraz gold layer? Jak to zadanie zautomatyzować? Czy można z tego wyciągnąć jeszcze jakieś wnioski?

Rozwiązanie:

W Databricks dostępne jest polecenie:

describe detail table_name

Umożliwia ono pokazanie rozmiaru w bajtach, wylistowanie ile plików zajmuje obecnie tabela. Pokazuje też kiedy zostało utworzona albo ostatnio załadowana.

Pokażę teraz w jaki sposób, wygląda skrypt, który dla schematu zbiera dane o wszystkich tabelach.

Jaki jest rozmiar tabeli w Databricks - przygotowanie

Zacznijmy od ustawienia parametrów. W widgetach ustal z jakiego schematu pobierasz dane i do jakiej tabeli je zapisujesz.

Definicja widgetów:

dbutils.widgets.text('target_schema', 'next_level_dm')
dbutils.widgets.text('user_tab_size_table_name', 'dbx_user_tab_size')

Pobranie ustawionej wartości z widetów:

in_target_schema = dbutils.widgets.get('target_schema')
in_user_tab_size = dbutils.widgets.get('user_tab_size_table_name')

Oraz import niezbędnych funkcji sparkowych do operacji na kolumnach.

from pyspark.sql.functions import col, lit

Ostatni punkt to wylistowanie wszystkich analizowanych tabel. Do tego posłuży tabela: dbx_user_tab_column, Zajrzyj do tego wpisu jeżeli jej jeszcze nie masz!

all_tables = spark.sql(f"select distinct table_name, substr(table_name,1,locate('_', table_name)-1) as table_prefix
from {in_target_schema}.dbx_user_tab_columns 
where table_name not like 'v%' and table_name not like 'dbx%' and table_name not like 'z%' ").collect()

Jaki jest rozmiar tabeli w Databricks - zbieranie wyników

Na początku definicja zmiennej, która będzie przechowywać wynikowy DataFrame oraz zaczynamy iterację po tabelach, pobranych w poleceniu powyżej.

table_size_df = None
for table in all_tables:
    table_name = table["table_name"]

Sprawdzamy czy tabela istnieje w schemacie w spark katalogu, żeby uniknąć ewentualnych błędów i wykonujemy zapytanie describe detail. Wyniki zbieramy w DataFrame.

if spark.catalog.tableExists(f"{in_target_schema}.{table_name}"):
table_details = spark.sql(f"describe detail {in_target_schema}.{table_name}")

Przyszła pora na wyliczenia dodatkowych kolumn. Liczymy liczbę wierszy w tabeli oraz rozmiar tabeli w GB oraz estymujemy rozmiar jednego pliku. Dodajemy też nazwę tabeli oraz jej prefix (to co znajduje się przed pierwszym podkreśleniem).

nbr_of_rows = spark.sql(f"select count(*) as cnt from {in_target_schema}.{table_name}").collect()[0]["cnt"]

table_details = table_details.withColumn("size_in_gb",col("sizeInBytes")/(1024*1024*1024))
.withColumn('size_per_file', col("sizeInBytes")/col("numFiles"))
.withColumn("nbr_of_rows",lit(nbr_of_rows)).withColumn("table_name",lit(table_name))
.withColumn("table_prefix",lit(table["table_prefix"]))

Ostatnia część w tej pętli to tworzenie nazw kolumn oraz tworzenie lub rozszerzanie DataFrame o właśnie wyliczone dane.

table_details = table_details.selectExpr("table_name","table_prefix","sizeInBytes as size_in_bytes","size_in_gb", "numFiles as nbr_of_files"
,"createdAt as created_at","lastModified as last_modified_at", "statistics","partitionColumns as partition_columns"
,"clusteringColumns as clustering_columns","nbr_of_rows","size_per_file")

table_size_df = table_details if table_size_df is None else table_size_df.unionAll(table_details)

Jaki jest rozmiar tabeli w Databricks - zapisywanie wyników

Teraz zostało już tylko zapisanie wyników. Najpierw stworzymy tymczasowy widok i potem dodamy do niego kolumnę audytową load_date, żeby wiedzieć, kiedy załadowana została tabela.

table_size_df.createOrReplaceTempView('v_user_tab_size')

spark.sql(f"""create or replace table {in_target_schema}.{in_user_tab_size} as 
            select us.*, current_timestamp() as load_date from v_user_tab_size us """)

Cały kod dostępny jak zawsze na GitHub:
https://github.com/rgogloza/nextlevelbi/blob/master/databricks/dbx_user_tab_size.ipynb

Jaki jest rozmiar tabeli w Databricks - dla dociekliwych

Rozmiar tabeli można sprawdzić też w inny sposób, służy do tego sparkowe polecenie:

describe table extended table_name

Pokazuje ono rozmiar tabeli w bajtach tylko, że niestety czasami ta wartość nie jest rzeczywista. Nie odpowiada temu jest w describe detail.

Dlaczego tak się dzieje? Czy da się zobaczyć poprawne wartości?

Tak oczywiście, tylko najpierw uruchom:

analyze table table_name compute statistics

To polecenia "odświeża" dane, które wyświetla describe table extended i wtedy masz spójne dane z tym co widzisz w describe detail. Z moich obserwacji wynika, że dane w describe detail są poprawne.