Database
 sql >> Baza danych >  >> RDS >> Database

Pytania do wywiadu z inżynierem danych w Pythonie

Chodzenie na rozmowę kwalifikacyjną może być czasochłonnym i męczącym procesem, a rozmowy techniczne mogą być jeszcze bardziej stresujące! Ten samouczek ma na celu przygotowanie Cię na niektóre typowe pytania, które napotkasz podczas rozmowy z inżynierem danych. Dowiesz się, jak odpowiadać na pytania dotyczące baz danych, Pythona i SQL.

Pod koniec tego samouczka będziesz w stanie:

  • Zrozum typowe pytania podczas rozmowy kwalifikacyjnej z inżynierem danych
  • Rozróżnij relacyjne i nierelacyjne bazy danych
  • Konfiguruj bazy danych za pomocą Pythona
  • Użyj Pythona do zapytań o dane

Bezpłatne pobieranie: Pobierz przykładowy rozdział ze sztuczek Pythona:książki, która pokazuje najlepsze praktyki Pythona z prostymi przykładami, które możesz zastosować natychmiast, aby napisać piękniejszy + Pythonic kod.


Zostać inżynierem danych

Rola inżynierii danych może być rozległa i zróżnicowana. Musisz mieć praktyczną wiedzę na temat wielu technologii i koncepcji. Inżynierowie danych są elastyczni w swoim myśleniu. W rezultacie mogą być biegli w wielu tematach, takich jak bazy danych, tworzenie oprogramowania, DevOps i big data.


Co robi inżynier danych?

Biorąc pod uwagę zróżnicowany zestaw umiejętności, rola inżyniera danych może obejmować wiele różnych opisów stanowisk. Inżynier danych może być odpowiedzialny za projektowanie baz danych, projektowanie schematów i tworzenie wielu rozwiązań bazodanowych. Ta praca może również obejmować administratora bazy danych.

Jako inżynier danych , możesz działać jako pomost między bazą danych a zespołami analizy danych. W takim przypadku będziesz również odpowiedzialny za czyszczenie i przygotowanie danych. Jeśli w grę wchodzą duże zbiory danych, Twoim zadaniem jest wymyślenie wydajnego rozwiązania dla tych danych. Ta praca może pokrywać się z rolą DevOps.

Będziesz także musiał wykonywać wydajne zapytania o dane w celu raportowania i analizy. Może być konieczna interakcja z wieloma bazami danych lub napisanie procedur składowanych. W przypadku wielu rozwiązań, takich jak witryny lub usługi o dużym natężeniu ruchu, może istnieć więcej niż jedna baza danych. W takich przypadkach inżynier danych jest odpowiedzialny za konfigurację baz danych, utrzymywanie ich i przesyłanie danych między nimi.



Jak Python może pomóc inżynierom danych?

Python jest znany jako szwajcarski scyzoryk wśród języków programowania. Jest to szczególnie przydatne w nauce o danych, systemach zaplecza i skryptach po stronie serwera. Dzieje się tak, ponieważ Python ma silne typowanie, prostą składnię i mnóstwo bibliotek innych firm do użycia. Pandas, SciPy, Tensorflow, SQLAlchemy i NumPy to jedne z najczęściej używanych bibliotek w produkcji w różnych branżach.

Co najważniejsze, Python skraca czas programowania, co oznacza mniejsze wydatki dla firm. Dla inżyniera danych większość wykonania kodu jest związana z bazą danych, a nie z procesorem. Z tego powodu warto wykorzystać prostotę Pythona, nawet kosztem niższej wydajności w porównaniu z językami kompilowanymi, takimi jak C# i Java.




Odpowiadanie na pytania z wywiadu z inżynierem danych

Teraz, gdy już wiesz, na czym może polegać Twoja rola, nadszedł czas, aby dowiedzieć się, jak odpowiedzieć na pytania podczas rozmowy kwalifikacyjnej inżyniera danych! Chociaż jest wiele do omówienia, w samouczku zobaczysz praktyczne przykłady Pythona, które poprowadzą Cię po drodze.



Pytania dotyczące relacyjnych baz danych

Bazy danych to jeden z najważniejszych elementów systemu. Bez nich nie może być państwa ani historii. Chociaż być może nie uważałeś projektowania bazy danych za priorytet, pamiętaj, że może to mieć znaczący wpływ na szybkość ładowania strony. W ciągu ostatnich kilku lat kilka dużych korporacji wprowadziło kilka nowych narzędzi i technik:

  • NoSQL
  • Bazy danych w pamięci podręcznej
  • Bazy danych wykresów
  • Obsługa NoSQL w bazach danych SQL

Te i inne techniki zostały wynalezione w celu zwiększenia szybkości przetwarzania żądań przez bazy danych. Prawdopodobnie będziesz musiał porozmawiać o tych koncepcjach podczas rozmowy z inżynierem danych, więc zajmijmy się kilkoma pytaniami!


P1:relacyjne a nierelacyjne bazy danych

relacyjna baza danych to taki, w którym dane są przechowywane w formie tabeli. Każda tabela ma schemat , czyli kolumny i typy wymagane przez rekord. Każdy schemat musi mieć co najmniej jeden klucz podstawowy, który jednoznacznie identyfikuje ten rekord. Innymi słowy, w Twojej bazie danych nie ma zduplikowanych wierszy. Co więcej, każda tabela może być powiązana z innymi tabelami za pomocą kluczy obcych.

Jednym z ważnych aspektów relacyjnych baz danych jest to, że zmiana w schemacie musi zostać zastosowana do wszystkich rekordów. Może to czasami powodować pęknięcia i duże bóle głowy podczas migracji. Nierelacyjne bazy danych podejść do rzeczy w inny sposób. Są one z natury pozbawione schematów, co oznacza, że ​​rekordy można zapisywać z różnymi schematami i inną, zagnieżdżoną strukturą. Rekordy mogą nadal mieć klucze podstawowe, ale zmiany w schemacie są dokonywane na zasadzie wpis po wpisie.

Będziesz musiał przeprowadzić test porównawczy prędkości w oparciu o rodzaj wykonywanej funkcji. Możesz wybrać INSERT , UPDATE , DELETE lub inną funkcję. Projekt schematu, indeksy, liczba agregacji i liczba rekordów również będą miały wpływ na tę analizę, więc musisz dokładnie przetestować. Więcej o tym, jak to zrobić, dowiesz się później.

Bazy danych różnią się także skalowalnością . Dystrybucja nierelacyjnej bazy danych może być mniej uciążliwa. Dzieje się tak, ponieważ zbiór powiązanych rekordów można łatwo przechowywać w określonym węźle. Z drugiej strony, relacyjne bazy danych wymagają więcej przemyśleń i zwykle wykorzystują system master-slave.



Przykład SQLite

Teraz, gdy już odpowiedziałeś, czym są relacyjne bazy danych, nadszedł czas, aby zagłębić się w Pythona! SQLite to wygodna baza danych, której można używać na komputerze lokalnym. Baza danych jest pojedynczym plikiem, co czyni ją idealną do celów prototypowania. Najpierw zaimportuj wymaganą bibliotekę Pythona i utwórz nową bazę danych:

import sqlite3

db = sqlite3.connect(':memory:')  # Using an in-memory database
cur = db.cursor()

Masz teraz połączenie z bazą danych w pamięci i masz gotowy obiekt kursora.

Następnie utworzysz następujące trzy tabele:

  1. Klient: Ta tabela będzie zawierać klucz podstawowy oraz imię i nazwisko klienta.
  2. Przedmioty: Ta tabela będzie zawierać klucz podstawowy, nazwę przedmiotu i cenę przedmiotu.
  3. Zakupione przedmioty :Ta tabela będzie zawierać numer zamówienia, datę i cenę. Łączy się również z kluczami podstawowymi w tabelach Items i Customer.

Teraz, gdy masz już wyobrażenie o tym, jak będą wyglądać Twoje stoły, możesz zacząć je tworzyć:

cur.execute('''CREATE TABLE IF NOT EXISTS Customer (
                id integer PRIMARY KEY,
                firstname varchar(255),
                lastname varchar(255) )''')
cur.execute('''CREATE TABLE IF NOT EXISTS Item (
                id integer PRIMARY KEY,
                title varchar(255),
                price decimal )''')
cur.execute('''CREATE TABLE IF NOT EXISTS BoughtItem (
                ordernumber integer PRIMARY KEY,
                customerid integer,
                itemid integer,
                price decimal,
                CONSTRAINT customerid
                    FOREIGN KEY (customerid) REFERENCES Customer(id),
                CONSTRAINT itemid
                    FOREIGN KEY (itemid) REFERENCES Item(id) )''')

Przesłałeś zapytanie do cur.execute() aby stworzyć swoje trzy stoły.

Ostatnim krokiem jest wypełnienie tabel danymi:

cur.execute('''INSERT INTO Customer(firstname, lastname)
               VALUES ('Bob', 'Adams'),
                      ('Amy', 'Smith'),
                      ('Rob', 'Bennet');''')
cur.execute('''INSERT INTO Item(title, price)
               VALUES ('USB', 10.2),
                      ('Mouse', 12.23),
                      ('Monitor', 199.99);''')
cur.execute('''INSERT INTO BoughtItem(customerid, itemid, price)
               VALUES (1, 1, 10.2),
                      (1, 2, 12.23),
                      (1, 3, 199.99),
                      (2, 3, 180.00),
                      (3, 2, 11.23);''') # Discounted price 

Teraz, gdy w każdej tabeli jest kilka rekordów, możesz użyć tych danych, aby odpowiedzieć na kilka dodatkowych pytań z wywiadu z inżynierem danych.



P2:Funkcje agregacji SQL

Funkcje agregacji to te, które wykonują operację matematyczną na zestawie wyników. Niektóre przykłady to AVG , COUNT , MIN , MAX i SUM . Często będziesz potrzebować GROUP BY i HAVING klauzule uzupełniające te agregacje. Jedną z przydatnych funkcji agregacji jest AVG , którego możesz użyć do obliczenia średniej z danego zestawu wyników:

>>>
>>> cur.execute('''SELECT itemid, AVG(price) FROM BoughtItem GROUP BY itemid''')
>>> print(cur.fetchall())
[(1, 10.2), (2, 11.73), (3, 189.995)]

Tutaj pobrałeś średnią cenę za każdy zakupiony przedmiot w Twojej bazie danych. Możesz zobaczyć, że element z itemid z 1 ma średnią cenę 10,20 USD.

Aby powyższe dane wyjściowe były łatwiejsze do zrozumienia, możesz wyświetlić nazwę elementu zamiast itemid :

>>>
>>> cur.execute('''SELECT item.title, AVG(boughtitem.price) FROM BoughtItem as boughtitem
...             INNER JOIN Item as item on (item.id = boughtitem.itemid)
...             GROUP BY boughtitem.itemid''')
...
>>> print(cur.fetchall())
[('USB', 10.2), ('Mouse', 11.73), ('Monitor', 189.995)]

Teraz łatwiej widać, że przedmiot o średniej cenie 10,20 USD to USB .

Inną przydatną agregacją jest SUM . Możesz użyć tej funkcji, aby wyświetlić całkowitą kwotę wydaną przez każdego klienta:

>>>
>>> cur.execute('''SELECT customer.firstname, SUM(boughtitem.price) FROM BoughtItem as boughtitem
...             INNER JOIN Customer as customer on (customer.id = boughtitem.customerid)
...             GROUP BY customer.firstname''')
...
>>> print(cur.fetchall())
[('Amy', 180), ('Bob', 222.42000000000002), ('Rob', 11.23)]

Klient o imieniu Amy wydał średnio około 180 USD, podczas gdy Rob wydał tylko 11,23 USD!

Jeśli twój ankieter lubi bazy danych, możesz odświeżyć zagnieżdżone zapytania, typy złączeń i kroki, jakie relacyjna baza danych podejmuje w celu wykonania zapytania.



P3:Przyspieszenie zapytań SQL

Szybkość zależy od różnych czynników, ale w większości zależy od tego, ile z poniższych jest obecnych:

  • Połączenia
  • Agregacje
  • Przejścia
  • Rekordy

Im większa liczba złączeń, tym większa złożoność i większa liczba przejść w tabelach. Wielokrotne sprzężenia są dość drogie do wykonania na kilku tysiącach rekordów obejmujących kilka tabel, ponieważ baza danych również musi buforować wynik pośredni! W tym momencie możesz zacząć zastanawiać się, jak zwiększyć rozmiar pamięci.

Na prędkość wpływa również to, czy istnieją indeksy obecne w bazie danych. Indeksy są niezwykle ważne i pozwalają szybko przeszukiwać tabelę i znaleźć dopasowanie do jakiejś kolumny określonej w zapytaniu.

Indeksy sortują rekordy kosztem dłuższego czasu wstawiania, a także trochę miejsca na przechowywanie. Wiele kolumn można połączyć w jeden indeks. Na przykład kolumny date i price mogą być łączone, ponieważ zapytanie zależy od obu warunków.



P4:Debugowanie zapytań SQL

Większość baz danych zawiera EXPLAIN QUERY PLAN opisujący kroki, jakie baza danych podejmuje w celu wykonania zapytania. W przypadku SQLite możesz włączyć tę funkcję, dodając EXPLAIN QUERY PLAN przed SELECT oświadczenie:

>>>
>>> cur.execute('''EXPLAIN QUERY PLAN SELECT customer.firstname, item.title, 
...                item.price, boughtitem.price FROM BoughtItem as boughtitem
...                INNER JOIN Customer as customer on (customer.id = boughtitem.customerid)
...                INNER JOIN Item as item on (item.id = boughtitem.itemid)''')
...
>>> print(cur.fetchall())
[(4, 0, 0, 'SCAN TABLE BoughtItem AS boughtitem'), 
(6, 0, 0, 'SEARCH TABLE Customer AS customer USING INTEGER PRIMARY KEY (rowid=?)'), 
(9, 0, 0, 'SEARCH TABLE Item AS item USING INTEGER PRIMARY KEY (rowid=?)')]

To zapytanie próbuje wyświetlić imię, tytuł przedmiotu, pierwotną cenę i cenę zakupu dla wszystkich zakupionych przedmiotów.

Oto jak wygląda sam plan zapytań:

SCAN TABLE BoughtItem AS boughtitem
SEARCH TABLE Customer AS customer USING INTEGER PRIMARY KEY (rowid=?)
SEARCH TABLE Item AS item USING INTEGER PRIMARY KEY (rowid=?)

Zauważ, że instrukcja fetch w kodzie Pythona zwraca tylko wyjaśnienie, ale nie wyniki. Dzieje się tak, ponieważ EXPLAIN QUERY PLAN nie jest przeznaczony do użytku w produkcji.




Pytania dotyczące nierelacyjnych baz danych

W poprzedniej sekcji przedstawiłeś różnice między relacyjnymi i nierelacyjnymi bazami danych oraz używałeś SQLite w Pythonie. Teraz skupisz się na NoSQL. Twoim celem jest podkreślenie jego mocnych stron, różnic i przypadków użycia.


Przykład MongoDB

Użyjesz tych samych danych co poprzednio, ale tym razem Twoją bazą będzie MongoDB. Ta baza danych NoSQL jest oparta na dokumentach i bardzo dobrze skaluje się. Po pierwsze, musisz zainstalować wymaganą bibliotekę Pythona:

$ pip install pymongo

Możesz także zainstalować społeczność kompasu MongoDB. Zawiera lokalne IDE, które idealnie nadaje się do wizualizacji bazy danych. Dzięki niemu możesz zobaczyć utworzone rekordy, utworzyć wyzwalacze i działać jako wizualny administrator bazy danych.

Uwaga: Aby uruchomić kod z tej sekcji, potrzebujesz działającego serwera bazy danych. Aby dowiedzieć się więcej o tym, jak to skonfigurować, zapoznaj się z wprowadzeniem do MongoDB i Pythona.

Oto jak tworzysz bazę danych i wstawiasz dane:

import pymongo

client = pymongo.MongoClient("mongodb://localhost:27017/")

# Note: This database is not created until it is populated by some data
db = client["example_database"]

customers = db["customers"]
items = db["items"]

customers_data = [{ "firstname": "Bob", "lastname": "Adams" },
                  { "firstname": "Amy", "lastname": "Smith" },
                  { "firstname": "Rob", "lastname": "Bennet" },]
items_data = [{ "title": "USB", "price": 10.2 },
              { "title": "Mouse", "price": 12.23 },
              { "title": "Monitor", "price": 199.99 },]

customers.insert_many(customers_data)
items.insert_many(items_data)

Jak mogłeś zauważyć, MongoDB przechowuje rekordy danych w kolekcjach , które są odpowiednikiem listy słowników w Pythonie. W praktyce MongoDB przechowuje dokumenty BSON.



P5:Wysyłanie zapytań do danych za pomocą MongoDB

Spróbujmy zreplikować BoughtItem najpierw tabelę, tak jak w SQL. Aby to zrobić, musisz dołączyć nowe pole do klienta. Dokumentacja MongoDB określa, że ​​operator słowa kluczowego ustaw można użyć do aktualizacji rekordu bez konieczności wpisywania wszystkich istniejących pól:

# Just add "boughtitems" to the customer where the firstname is Bob
bob = customers.update_many(
        {"firstname": "Bob"},
        {
            "$set": {
                "boughtitems": [
                    {
                        "title": "USB",
                        "price": 10.2,
                        "currency": "EUR",
                        "notes": "Customer wants it delivered via FedEx",
                        "original_item_id": 1
                    }
                ]
            },
        }
    )

Zwróć uwagę, jak dodałeś dodatkowe pola do customer bez wcześniejszego wyraźnego zdefiniowania schematu. Fajnie!

W rzeczywistości możesz zaktualizować innego klienta za pomocą nieco zmienionego schematu:

amy = customers.update_many(
        {"firstname": "Amy"},
        {
            "$set": {
                "boughtitems":[
                    {
                        "title": "Monitor",
                        "price": 199.99,
                        "original_item_id": 3,
                        "discounted": False
                    }
                ]
            } ,
        }
    )
print(type(amy))  # pymongo.results.UpdateResult

Podobnie jak SQL, bazy danych oparte na dokumentach umożliwiają również wykonywanie zapytań i agregacji. Jednak funkcjonalność może się różnić zarówno pod względem składniowym, jak i podstawowym wykonaniem. W rzeczywistości mogłeś zauważyć, że MongoDB rezerwuje $ znak, aby określić polecenie lub agregację w rekordach, na przykład $group . Możesz dowiedzieć się więcej o tym zachowaniu w oficjalnych dokumentach.

Możesz wykonywać zapytania tak samo, jak w SQL. Aby rozpocząć, możesz utworzyć indeks:

>>>
>>> customers.create_index([("name", pymongo.DESCENDING)])

Jest to opcjonalne, ale przyspiesza zapytania wymagające wyszukiwania nazw.

Następnie możesz pobrać nazwy klientów posortowane w kolejności rosnącej:

>>>
>>> items = customers.find().sort("name", pymongo.ASCENDING)

Możesz także przeglądać i drukować kupione przedmioty:

>>>
>>> for item in items:
...     print(item.get('boughtitems'))    
...
None
[{'title': 'Monitor', 'price': 199.99, 'original_item_id': 3, 'discounted': False}]
[{'title': 'USB', 'price': 10.2, 'currency': 'EUR', 'notes': 'Customer wants it delivered via FedEx', 'original_item_id': 1}]

Możesz nawet pobrać listę unikalnych nazw w bazie danych:

>>>
>>> customers.distinct("firstname")
['Bob', 'Amy', 'Rob']

Teraz, gdy znasz nazwiska klientów w swojej bazie danych, możesz utworzyć zapytanie, aby uzyskać informacje o nich:

>>>
>>> for i in customers.find({"$or": [{'firstname':'Bob'}, {'firstname':'Amy'}]}, 
...                                  {'firstname':1, 'boughtitems':1, '_id':0}):
...     print(i)
...
{'firstname': 'Bob', 'boughtitems': [{'title': 'USB', 'price': 10.2, 'currency': 'EUR', 'notes': 'Customer wants it delivered via FedEx', 'original_item_id': 1}]}
{'firstname': 'Amy', 'boughtitems': [{'title': 'Monitor', 'price': 199.99, 'original_item_id': 3, 'discounted': False}]}

Oto równoważne zapytanie SQL:

SELECT firstname, boughtitems FROM customers WHERE firstname LIKE ('Bob', 'Amy')

Zauważ, że chociaż składnia może się nieznacznie różnić, istnieje drastyczna różnica w sposobie wykonywania zapytań pod maską. Należy się tego spodziewać ze względu na różne struktury zapytań i przypadki użycia między bazami danych SQL i NoSQL.



P6:NoSQL kontra SQL

Jeśli masz stale zmieniający się schemat, taki jak informacje dotyczące przepisów finansowych, NoSQL może modyfikować rekordy i zagnieżdżać powiązane informacje. Wyobraź sobie liczbę złączeń, które musiałbyś wykonać w SQL, gdybyś miał osiem rzędów zagnieżdżania! Jednak taka sytuacja jest bardziej powszechna, niż mogłoby się wydawać.

A co, jeśli chcesz generować raporty, wydobywać informacje z tych danych finansowych i wyciągać wnioski? W takim przypadku musisz uruchamiać złożone zapytania, a SQL wydaje się być pod tym względem szybszy.

Uwaga: Bazy danych SQL, w szczególności PostgreSQL, również udostępniły funkcję, która umożliwia wstawianie danych JSON zawierających zapytania jako część rekordu. Chociaż może to łączyć to, co najlepsze z obu światów, szybkość może być niepokojąca.

Wykonywanie zapytań o nieustrukturyzowane dane z bazy danych NoSQL jest szybsze niż w przypadku zapytań dotyczących pól JSON z kolumny typu JSON w PostgreSQL. Zawsze możesz wykonać test porównawczy prędkości, aby uzyskać ostateczną odpowiedź.

Niemniej jednak ta funkcja może zmniejszyć zapotrzebowanie na dodatkową bazę danych. Czasami marynowane lub serializowane obiekty są przechowywane w rekordach w postaci typów binarnych, a następnie deserializowane przy odczycie.

Szybkość nie jest jednak jedyną miarą. Będziesz także chciał wziąć pod uwagę takie rzeczy, jak transakcje, atomowość, trwałość i skalowalność. Transakcje są ważne w aplikacjach finansowych i takie funkcje mają pierwszeństwo.

Ponieważ istnieje szeroka gama baz danych, każda z własnymi funkcjami, zadaniem inżyniera danych jest podjęcie świadomej decyzji, której bazy danych użyć w każdej aplikacji. Aby uzyskać więcej informacji, możesz przeczytać o właściwościach ACID związanych z transakcjami w bazach danych.

Możesz również zostać zapytany, jakie inne bazy danych znasz podczas rozmowy z inżynierem danych. Istnieje kilka innych odpowiednich baz danych, z których korzysta wiele firm:

  • Elastyczne wyszukiwanie jest bardzo wydajny w wyszukiwaniu tekstowym. Wykorzystuje swoją bazę danych opartą na dokumentach, aby stworzyć potężne narzędzie wyszukiwania.
  • Traszka DB łączy ZODB i PostgreSQL JSONB, aby stworzyć przyjazną dla Pythona bazę danych NoSQL.
  • InfluxDB jest używany w aplikacjach szeregów czasowych do przechowywania zdarzeń.

Lista jest długa, ale to ilustruje, w jaki sposób szeroka gama dostępnych baz danych zaspokaja ich niszową branżę.




Pytania dotyczące baz danych pamięci podręcznej

Bazy danych pamięci podręcznej przechowywać często używane dane. Żyją obok głównych baz danych SQL i NoSQL. Ich celem jest zmniejszenie obciążenia i szybsze obsługiwanie żądań.


Przykład Redisa

Omówiłeś bazy danych SQL i NoSQL dotyczące długoterminowych rozwiązań pamięci masowej, ale co z szybszym, bardziej natychmiastowym przechowywaniem? Jak inżynier danych może zmienić szybkość pobierania danych z bazy danych?

Typowe aplikacje internetowe bardzo często pobierają powszechnie używane dane, takie jak profil lub imię użytkownika. Jeśli wszystkie dane znajdują się w jednej bazie danych, liczba trafień serwer bazy danych będzie przesadny i niepotrzebny. W związku z tym potrzebne jest szybsze i bardziej natychmiastowe rozwiązanie do przechowywania.

Chociaż zmniejsza to obciążenie serwera, powoduje to również dwa bóle głowy dla inżyniera danych, zespołu zaplecza i zespołu DevOps. Po pierwsze, będziesz potrzebować bazy danych, która ma szybszy czas odczytu niż główna baza danych SQL lub NoSQL. Jednak zawartość obu baz danych musi w końcu się zgadzać. (Witamy w problemie spójności stanu między bazami danych! Ciesz się.)

Drugim problemem jest to, że DevOps musi teraz martwić się skalowalnością, nadmiarowością i tak dalej w przypadku nowej bazy danych pamięci podręcznej. W następnej sekcji zagłębisz się w takie problemy z pomocą Redis.



P7:Jak korzystać z baz danych pamięci podręcznej

Być może masz wystarczająco dużo informacji ze wstępu, aby odpowiedzieć na to pytanie! baza danych pamięci podręcznej to szybkie rozwiązanie do przechowywania danych używane do przechowywania krótkotrwałych, ustrukturyzowanych lub nieustrukturyzowanych danych. Można ją podzielić na partycje i skalować zgodnie z Twoimi potrzebami, ale zazwyczaj ma znacznie mniejszy rozmiar niż główna baza danych. Z tego powodu baza danych pamięci podręcznej może znajdować się w pamięci, co pozwala ominąć potrzebę odczytu z dysku.

Uwaga: Jeśli kiedykolwiek używałeś słowników w Pythonie, Redis ma tę samą strukturę. To sklep klucz-wartość, w którym możesz SET i GET dane tak jak w Pythonie dict .

Gdy nadejdzie żądanie, najpierw sprawdzasz bazę danych pamięci podręcznej, a następnie główną bazę danych. W ten sposób możesz zapobiec dotarciu niepotrzebnych i powtarzających się żądań do głównego serwera bazy danych. Ponieważ baza danych pamięci podręcznej ma krótszy czas odczytu, zyskujesz również na zwiększeniu wydajności!

Możesz użyć pip, aby zainstalować wymaganą bibliotekę:

$ pip install redis

Rozważ teraz prośbę o pobranie nazwy użytkownika z jego identyfikatora:

import redis
from datetime import timedelta

# In a real web application, configuration is obtained from settings or utils
r = redis.Redis()

# Assume this is a getter handling a request
def get_name(request, *args, **kwargs):
    id = request.get('id')
    if id in r:
        return r.get(id)  # Assume that we have an {id: name} store
    else:
        # Get data from the main DB here, assume we already did it
        name = 'Bob'
        # Set the value in the cache database, with an expiration time
        r.setex(id, timedelta(minutes=60), value=name)
        return name

Ten kod sprawdza, czy nazwa jest w Redis, używając id klucz. Jeśli nie, nazwa jest ustawiana z czasem wygaśnięcia, którego używasz, ponieważ pamięć podręczna jest krótkotrwała.

A co, jeśli ankieter zapyta Cię, co jest nie tak z tym kodem? Twoja odpowiedź powinna brzmieć, że nie ma obsługi wyjątków! Bazy danych mogą mieć wiele problemów, takich jak zerwane połączenia, więc zawsze warto spróbować złapać te wyjątki.




Pytania dotyczące wzorców projektowych i koncepcji ETL

W dużych aplikacjach często będziesz używać więcej niż jednego typu bazy danych. W rzeczywistości możliwe jest korzystanie z PostgreSQL, MongoDB i Redis w jednej aplikacji! Jednym z trudnych problemów jest radzenie sobie ze zmianami stanu między bazami danych, co naraża programistę na problemy ze spójnością. Rozważ następujący scenariusz:

  1. Wartość w bazie danych #1 jest aktualizowana.
  2. Ta sama wartość w Bazie danych nr 2 jest taki sam (nie aktualizowany).
  3. Zapytanie działa w Bazie Danych #2.

Teraz masz niespójny i nieaktualny wynik! Wyniki zwrócone z drugiej bazy danych nie będą odzwierciedlać zaktualizowanej wartości w pierwszej. Może się to zdarzyć w przypadku dowolnych dwóch baz danych, ale jest to szczególnie powszechne, gdy główną bazą danych jest baza danych NoSQL, a informacje są przekształcane w SQL na potrzeby zapytań.

Bazy danych mogą mieć pracowników w tle, którzy mogą rozwiązywać takie problemy. Ci pracownicy wydobywają dane z jednej bazy danych, przekształć w jakiś sposób i załaduj do docelowej bazy danych. Podczas konwersji z bazy danych NoSQL na bazę SQL, proces Extract, transform, load (ETL) wykonuje następujące kroki:

  1. Wyciąg: Za każdym razem, gdy rekord jest tworzony, aktualizowany i tak dalej, istnieje wyzwalacz MongoDB. Funkcja wywołania zwrotnego jest wywoływana asynchronicznie w osobnym wątku.
  2. Przekształć: Części rekordu są wyodrębniane, normalizowane i umieszczane w prawidłowej strukturze danych (lub wierszu) w celu wstawienia do SQL.
  3. Załaduj: Baza danych SQL jest aktualizowana partiami lub jako pojedynczy rekord w przypadku dużych zapisów.

Ten przepływ pracy jest dość powszechny w aplikacjach finansowych, gier i raportowania. W takich przypadkach stale zmieniający się schemat wymaga bazy danych NoSQL, ale raportowanie, analiza i agregacja wymagają bazy danych SQL.


P8:Wyzwania ETL

Istnieje kilka trudnych koncepcji w ETL, w tym następujące:

  • Wielkie dane
  • Problemy ze stanem
  • Pracownicy asynchroniczni
  • Dopasowywanie typów

I tak dalej! Ponieważ jednak etapy procesu ETL są dobrze zdefiniowane i logiczne, inżynierowie danych i zaplecza będą zwykle bardziej martwić się wydajnością i dostępnością niż implementacją.

Jeśli Twoja aplikacja zapisuje tysiące rekordów na sekundę do MongoDB, Twój pracownik ETL musi nadążyć za przekształcaniem, ładowaniem i dostarczaniem danych do użytkownika w żądanym formularzu. Szybkość i opóźnienia mogą stać się problemem, dlatego pracownicy ci są zazwyczaj pisani w szybkich językach. Możesz użyć skompilowanego kodu do kroku transformacji, aby przyspieszyć działanie, ponieważ ta część jest zwykle związana z procesorem.

Uwaga: Wielokrotne przetwarzanie i rozdzielanie pracowników to inne rozwiązania, które warto rozważyć.

Jeśli masz do czynienia z wieloma funkcjami intensywnie korzystającymi z procesora, możesz wypróbować Numbę. Ta biblioteka kompiluje funkcje, aby przyspieszyć ich wykonanie. Co najlepsze, można to łatwo zaimplementować w Pythonie, chociaż istnieją pewne ograniczenia dotyczące funkcji, które mogą być używane w tych skompilowanych funkcjach.



P9:Wzorce projektowe w Big Data

Wyobraź sobie, że Amazon musi stworzyć system rekomendacji sugerować użytkownikom odpowiednie produkty. Zespół analityków danych potrzebuje danych i to dużo! Idą do ciebie, inżyniera danych, i proszą o utworzenie oddzielnej tymczasowej hurtowni bazy danych. To tam oczyszczą i przekształcą dane.

Możesz być zszokowany otrzymaniem takiej prośby. Kiedy masz terabajty danych, będziesz potrzebować wielu komputerów do obsługi wszystkich tych informacji. Funkcja agregacji bazy danych może być bardzo złożoną operacją. W jaki sposób możesz wyszukiwać, agregować i wykorzystywać stosunkowo duże dane w efektywny sposób?

Apache początkowo wprowadził MapReduce, który podąża za mapą, tasuj, zmniejszaj przepływ pracy. Pomysł polega na mapowaniu różnych danych na oddzielnych maszynach, zwanych również klastrami. Następnie możesz wykonać pracę na danych, pogrupowanych według klucza, a na koniec zagregować dane w końcowym etapie.

Ten przepływ pracy jest nadal używany do dziś, ale ostatnio zanika na korzyść Sparka. Wzorzec projektowy stanowi jednak podstawę większości przepływów pracy dotyczących dużych zbiorów danych i jest bardzo intrygującą koncepcją. Więcej informacji na temat MapReduce można znaleźć w IBM Analytics.



P10:Wspólne aspekty procesu ETL i przepływów pracy Big Data

Możesz pomyśleć, że to dość dziwne pytanie, ale jest to po prostu sprawdzenie Twojej wiedzy z zakresu informatyki, a także ogólnej wiedzy i doświadczenia w zakresie projektowania.

Oba przepływy pracy są zgodne z zasadą Producent-Konsument wzór. Pracownik (producent) wytwarza pewnego rodzaju dane i wysyła je do potoku. Ten potok może przybierać różne formy, w tym komunikaty sieciowe i wyzwalacze. Po wydaniu danych przez Producenta, Konsument konsumuje je i wykorzystuje. Pracownicy ci zazwyczaj pracują w sposób asynchroniczny i są wykonywane w oddzielnych procesach.

Producenta można przyrównać do etapów wyodrębniania i przekształcania procesu ETL. Podobnie w przypadku dużych zbiorów danych mapper może być postrzegany jako Producent, podczas gdy reduktor jest faktycznie Konsumentem. To oddzielenie obaw jest niezwykle ważne i skuteczne w rozwoju i projektowaniu architektury aplikacji.




Wniosek

Gratulacje! Omówiłeś dużo tematu i odpowiedziałeś na kilka pytań podczas wywiadu z inżynierem danych. Teraz rozumiesz nieco więcej na temat wielu różnych czapek, które może nosić inżynier danych, a także jakie są Twoje obowiązki w odniesieniu do baz danych, projektowania i przepływu pracy.

Uzbrojeni w tę wiedzę, możesz teraz:

  • Używaj Pythona z bazami danych SQL, NoSQL i pamięci podręcznej
  • Używaj Pythona w aplikacjach ETL i zapytaniach
  • Planuj projekty z wyprzedzeniem, pamiętając o projektowaniu i przepływie pracy

Chociaż pytania podczas rozmowy kwalifikacyjnej mogą być różne, byłeś narażony na wiele tematów i nauczyłeś się myśleć nieszablonowo w wielu różnych obszarach informatyki. Teraz jesteś gotowy na niesamowity wywiad!



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak używać „Lubię to” w SQL

  2. Dowiedz się, jak obsługiwać wyjątki w PL/SQL

  3. Hekaton z niespodzianką:In-memory TVP – część 1

  4. 4 sposoby na uzyskanie definicji procedury składowanej przy użyciu języka Transact-SQL

  5. Jak zainstalować Nextcloud 15 na Ubuntu 18.04