Problem:

Czy Optimize automatycznie usuwa stare pliki? Czy one są ciągle dostępne? Czy po uruchomieniu Optimize na tabeli, liczba wykorzystywanego miejsca na Storage Account będzie mniejsza czy większa?

Po wykonaniu polecenia Optimize, Databricks pokazuje, że tabela jest reprezentowana przez mniejszą liczbę plików, natomiast na Storage Account liczba plików wzrosła. Jak to rozumieć?

Databricks pokazuje rozmiar tabeli / pliku, który nie jest zgodny z tym co widać na Azure Storage account. Która wartość jest prawidłowa? Jak z poziomu Databricks sprawdzić rozmiar pliku?

Rozwiązanie:

Z poziomu Databricks uruchom polecenie:

dbutils.fs.ls(file_path)

Wtedy zobaczysz ile rzeczywiście pliki zajmują. Jeżeli chcesz usunąć niepotrzebne pliki użyj polecenia Vacuum. Tylko pamiętaj, że domyślnie Vacuum, pozostawia na file systemie pliki stworzone w ciągu ostatnich 7 dni.

Jaki rozmiar ma tabela w Databricks?

Jak pamiętasz:

describe detail nazwa_tabeli 

pokazuje ile miejsca zajmuje tabela.

Tylko, że to nie jest wszystko.

Na file systemie Databricks zostawia stare pliki, tak na wszelki wypadek, jakby jeszcze jakiś proces pisał lub czytał z tych plików. Albo tak dla Ciebie, jakbyś się kiedyś chciał wrócić do tych plików. Albo gdyby coś poszło nie tak w Databricks, żeby można było wcześniejszą wersję danych odnaleźć.

Dla przykładu tabela z zamówieniami f_orderbook przed uruchomieniem Optimize pokazywała:

numFiles: 200
sizeInBytes: 2 437 013 826

Ile miejsce zajmowane jest w chmurze?

dbutils.fs.ls('abfss://dbx1@next-level-bi01.dfs.core.windows.net/next-level-dm/f_orderbook')

Pokazuje, nie 200 tylko 401 plików i zajmują łącznie: 4 874 094 450, czyli 2 razy więcej niż pokazuje DBX.

Co zrobi Optimize?

Dodajmy kolejną komplikację.

Jak widzisz nie jest to zbyt optymalne ułożenie danych. Średnio plik ma 11 MB (2 437 013 826 / 200).

Uruchommy Optimize. Całkowity rozmiar plików się nie zmieni, natomiast będą one większe i co za tym idzie Sparkowi powinno się je łatwiej czytać.

Po wykoaniu optimize:

{
    "numFilesAdded": 10,
    "numFilesRemoved": 200,
    "filesAdded": {
        "min": 60606926,
        "max": 268222509,
        "avg": 243689823.5,
        "totalFiles": 10,
        "totalSize": 2436898235
    },
    "filesRemoved": {
        "min": 11591211,
        "max": 12818532,
        "avg": 12185069.13,
        "totalFiles": 200,
        "totalSize": 2437013826
    } ..
}

Tak jak się spodziewaliśmy, liczba plików się zmniejszyła. Zobaczmy co się stało na file systemie:

dbutils.fs.ls('abfss://dbx1@next-level-bi01.dfs.core.windows.net/next-level-dm/f_orderbook')

Teraz już mamy 411 plików. 400, które były poprzednio i 10 nowych, łączny rozmiar danych zajmowanych przez pliki to: 7 310 992 685.

Super 😉

Databricks nic sam nie skasował, jeżeli jesteś pewny, że tych starych plików nikt nie używa, to można je teraz usunąć.

Najłatwiej zrobić to poleceniem Vacuum.

Mój Vacuum nie działa?

U mnie po uruchomieniu polecenia Vacuum nic się nie stało. Najstarsze pliki zostały utworzone 3 dni temu.

Vacuum ma takie ograniczenie / funkcjonalność, że nie usuwa plików stworzonych w ciągu ostatnich 7 dni czyli 168 godzin.

https://docs.databricks.com/en/sql/language-manual/delta-vacuum.html

Spróbujmy usunąć pliki, który mają mniej niż godzinę.

vacuum next_level_dm.f_orderbook retain 1 hours

Ja dostałem taki piękny błąd:

IllegalArgumentException: requirement failed: Are you sure you would like to vacuum files with such a low retention period? I

f you have writers that are currently writing to this table, there is a risk that you may corrupt the state of your Delta table. 

If you are certain that there are no operations being performed on this table, such as insert/upsert/delete/optimize, then you may turn off this check by setting: spark.databricks.delta.retentionDurationCheck.enabled = false 

If you are not sure, please use a value not less than "168 hours".

Sprawdzenie, co jest ustawione w retentionDurationCheck

print(spark.conf.get('spark.databricks.delta.retentionDurationCheck.enabled'))

W tym momencie jesteśmy pewni co robimy, więc ustawmy:

spark.conf.set("spark.databricks.delta.retentionDurationCheck.enabled", False)

Jeżeli chcesz podejrzeć jakie pliki będą usunięte uruchom polecenie vacuum z opcją dry run:

vacuum next_level_dm.f_orderbook retain 1 hours dry run

Jesteś już pewny, że wszystko chcesz usunąć? To działamy:

vacuum next_level_dm.f_orderbook retain 1 hours

Po usunięciu plików przez polecenie vacuum wylistujmy ile zajmują pliki:

dbutils.fs.ls('abfss://dbx1@next-level-bi01.dfs.core.windows.net/next-level-dm/f_orderbook')

Wreszcie jest tak, jak oczekiwałem. Ls zwrócił 11 plików (10 plików z danymi i 1 plik logów) . Rozmiar zajmowanych pików wynosi 2 436 898 235 czyli dokładnie tyle co pokazywał Describe detail.

Dotarliśmy tam gdzie chcieliśmy 🙂

Warte zapamiętania

Optimize nie usuwa plików, tylko tworzy nowe bardziej optymalnie ułożone.

Vacum nie usuwa plików stworzonych w ciągu ostatnich 7 dni. Modyfikacja domyślnych ustawień
spark.conf.set("spark.databricks.delta.retentionDurationCheck.enabled", False)
Działa tylko w ramach sesji.

Describe detail pokazuje ile danych zajmuje tabela ale nie pokazuje wszystkich plików które miały związek z tą tabelą na file systemie.

dbutils.fs.ls listuje wszystkie pliki kiedykolwiek powiązane z tabelą wciąż dostępne na Storage Account. W ten sposób najlepiej sprawdzisz ile danych jest albo było związanych z tabelą.