Database
 sql >> Base de données >  >> RDS >> Database

Questions d'entretien d'ingénieur de données avec Python

Aller aux entretiens peut être un processus chronophage et fatigant, et les entretiens techniques peuvent être encore plus stressants ! Ce didacticiel vise à vous préparer à certaines questions courantes que vous rencontrerez lors de votre entretien avec un ingénieur de données. Vous apprendrez à répondre aux questions sur les bases de données, Python et SQL.

À la fin de ce didacticiel, vous serez en mesure de :

  • Comprendre les questions courantes d'un entretien avec un ingénieur de données
  • Distinguer les bases de données relationnelles et non relationnelles
  • Configurer des bases de données à l'aide de Python
  • Utiliser Python pour interroger les données

Téléchargement gratuit : Obtenez un exemple de chapitre de Python Tricks :le livre qui vous montre les meilleures pratiques de Python avec des exemples simples que vous pouvez appliquer instantanément pour écrire du code + Pythonic plus beau.


Devenir ingénieur de données

Le rôle de l'ingénierie des données peut être vaste et varié. Vous devrez avoir une connaissance pratique de plusieurs technologies et concepts. Les ingénieurs de données sont flexibles dans leur façon de penser. Par conséquent, ils peuvent maîtriser plusieurs sujets, tels que les bases de données, le développement de logiciels, DevOps et le Big Data.


Que fait un ingénieur de données ?

Compte tenu de ses compétences variées, un rôle d'ingénieur de données peut couvrir de nombreuses descriptions de poste différentes. Un ingénieur de données peut être responsable de la conception de bases de données, de la conception de schémas et de la création de plusieurs solutions de bases de données. Ce travail peut également impliquer un administrateur de base de données.

En tant qu'ingénieur de données , vous pouvez servir de pont entre la base de données et les équipes de science des données. Dans ce cas, vous serez également responsable du nettoyage et de la préparation des données. Si le Big Data est impliqué, il vous incombe de trouver une solution efficace pour ces données. Ce travail peut chevaucher le rôle DevOps.

Vous devrez également effectuer des requêtes de données efficaces pour les rapports et l'analyse. Vous devrez peut-être interagir avec plusieurs bases de données ou écrire des procédures stockées. Pour de nombreuses solutions telles que les sites Web ou les services à fort trafic, plusieurs bases de données peuvent être présentes. Dans ces cas, l'ingénieur de données est responsable de la configuration des bases de données, de leur maintenance et du transfert de données entre elles.



Comment Python peut-il aider les ingénieurs de données ?

Python est connu pour être le couteau suisse des langages de programmation. Il est particulièrement utile dans la science des données, les systèmes backend et les scripts côté serveur. C'est parce que Python a un typage fort, une syntaxe simple et une abondance de bibliothèques tierces à utiliser. Pandas, SciPy, Tensorflow, SQLAlchemy et NumPy font partie des bibliothèques les plus utilisées en production dans différents secteurs.

Plus important encore, Python réduit le temps de développement, ce qui signifie moins de dépenses pour les entreprises. Pour un ingénieur de données, la plupart des exécutions de code sont liées à la base de données et non au processeur. Pour cette raison, il est logique de capitaliser sur la simplicité de Python, même au prix de performances plus lentes par rapport aux langages compilés tels que C# et Java.




Répondre aux questions de l'entretien avec un ingénieur de données

Maintenant que vous savez en quoi consiste votre rôle, il est temps d'apprendre à répondre à quelques questions d'entretien avec un ingénieur de données ! Bien qu'il y ait beaucoup de terrain à couvrir, vous verrez des exemples pratiques de Python tout au long du didacticiel pour vous guider tout au long du processus.



Questions sur les bases de données relationnelles

Les bases de données sont l'un des composants les plus cruciaux d'un système. Sans eux, il ne peut y avoir ni État ni histoire. Bien que vous n'ayez peut-être pas considéré la conception de la base de données comme une priorité, sachez qu'elle peut avoir un impact significatif sur la rapidité de chargement de votre page. Au cours des dernières années, plusieurs grandes entreprises ont introduit plusieurs nouveaux outils et techniques :

  • NoSQL
  • Bases de données de cache
  • Bases de données de graphes
  • Compatibilité NoSQL dans les bases de données SQL

Ces techniques et d'autres ont été inventées pour essayer d'augmenter la vitesse à laquelle les bases de données traitent les requêtes. Vous aurez probablement besoin de parler de ces concepts lors de votre entretien avec un ingénieur de données, alors passons en revue quelques questions !


Q1 :Bases de données relationnelles et non relationnelles

Une base de données relationnelle est celui où les données sont stockées sous la forme d'un tableau. Chaque table a un schéma , qui correspond aux colonnes et aux types qu'un enregistrement doit avoir. Chaque schéma doit avoir au moins une clé primaire qui identifie de manière unique cet enregistrement. En d'autres termes, il n'y a pas de lignes en double dans votre base de données. De plus, chaque table peut être liée à d'autres tables à l'aide de clés étrangères.

Un aspect important des bases de données relationnelles est qu'une modification de schéma doit être appliquée à tous les enregistrements. Cela peut parfois occasionner des casses et de gros maux de tête lors des migrations. Bases de données non relationnelles aborder les choses d'une manière différente. Ils sont intrinsèquement sans schéma, ce qui signifie que les enregistrements peuvent être enregistrés avec différents schémas et avec une structure imbriquée différente. Les enregistrements peuvent toujours avoir des clés primaires, mais une modification du schéma est effectuée entrée par entrée.

Vous devrez effectuer un test de comparaison de vitesse en fonction du type de fonction en cours d'exécution. Vous pouvez choisir INSERT , UPDATE , DELETE , ou une autre fonction. La conception du schéma, les index, le nombre d'agrégations et le nombre d'enregistrements affecteront également cette analyse, vous devrez donc effectuer des tests approfondis. Vous en apprendrez plus sur la façon de procéder plus tard.

Les bases de données diffèrent également par leur évolutivité . Une base de données non relationnelle peut être moins compliquée à distribuer. En effet, une collection d'enregistrements associés peut être facilement stockée sur un nœud particulier. En revanche, les bases de données relationnelles nécessitent plus de réflexion et utilisent généralement un système maître-esclave.



Un exemple SQLite

Maintenant que vous avez répondu à ce que sont les bases de données relationnelles, il est temps de creuser dans Python ! SQLite est une base de données pratique que vous pouvez utiliser sur votre machine locale. La base de données est un fichier unique, ce qui la rend idéale à des fins de prototypage. Tout d'abord, importez la bibliothèque Python requise et créez une nouvelle base de données :

import sqlite3

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

Vous êtes maintenant connecté à une base de données en mémoire et votre objet curseur est prêt à fonctionner.

Ensuite, vous allez créer les trois tables suivantes :

  1. Client : Cette table contiendra une clé primaire ainsi que les nom et prénom du client.
  2. Articles : Cette table contiendra une clé primaire, le nom de l'article et le prix de l'article.
  3. Articles achetés :Ce tableau contiendra un numéro de commande, une date et un prix. Il se connectera également aux clés primaires dans les tables Items et Customer.

Maintenant que vous avez une idée de ce à quoi ressembleront vos tableaux, vous pouvez continuer et les créer :

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) )''')

Vous avez passé une requête à cur.execute() pour créer vos trois tables.

La dernière étape consiste à remplir vos tableaux avec des données :

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 

Maintenant qu'il y a quelques enregistrements dans chaque table, vous pouvez utiliser ces données pour répondre à quelques autres questions d'entretien avec les ingénieurs de données.



Q2 :Fonctions d'agrégation SQL

Fonctions d'agrégation sont ceux qui effectuent une opération mathématique sur un ensemble de résultats. Quelques exemples incluent AVG , COUNT , MIN , MAX , et SUM . Souvent, vous aurez besoin de GROUP BY et HAVING clauses pour compléter ces agrégations. Une fonction d'agrégation utile est AVG , que vous pouvez utiliser pour calculer la moyenne d'un ensemble de résultats donné :

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

Ici, vous avez récupéré le prix moyen de chacun des articles achetés dans votre base de données. Vous pouvez voir que l'élément avec un itemid de 1 a un prix moyen de 10,20 $.

Pour rendre la sortie ci-dessus plus facile à comprendre, vous pouvez afficher le nom de l'élément au lieu de 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)]

Maintenant, vous voyez plus facilement que l'article avec un prix moyen de 10,20 € est le USB .

Une autre agrégation utile est SUM . Vous pouvez utiliser cette fonction pour afficher le montant total dépensé par chaque client :

>>>
>>> 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)]

En moyenne, la cliente nommée Amy a dépensé environ 180 $, tandis que Rob n'a dépensé que 11,23 $ !

Si votre intervieweur aime les bases de données, vous voudrez peut-être approfondir les requêtes imbriquées, les types de jointure et les étapes suivies par une base de données relationnelle pour effectuer votre requête.



Q3 :Accélération des requêtes SQL

La vitesse dépend de divers facteurs, mais elle est principalement affectée par le nombre de chacun des éléments suivants :

  • Joints
  • Agrégations
  • Traversées
  • Enregistrements

Plus le nombre de jointures est élevé, plus la complexité est élevée et plus le nombre de traversées dans les tables est important. Les jointures multiples sont assez coûteuses à réaliser sur plusieurs milliers d'enregistrements impliquant plusieurs tables car la base de données doit également mettre en cache le résultat intermédiaire ! À ce stade, vous pourriez commencer à réfléchir à la façon d'augmenter la taille de votre mémoire.

La vitesse est également affectée par la présence ou non d'indices présents dans la base de données. Les indices sont extrêmement importants et vous permettent de rechercher rapidement dans une table et de trouver une correspondance pour une colonne spécifiée dans la requête.

Les index trient les enregistrements au prix d'un temps d'insertion plus élevé, ainsi que d'un certain stockage. Plusieurs colonnes peuvent être combinées pour créer un index unique. Par exemple, les colonnes date et price peuvent être combinés car votre requête dépend des deux conditions.



Q4 :Débogage des requêtes SQL

La plupart des bases de données incluent un EXPLAIN QUERY PLAN qui décrit les étapes suivies par la base de données pour exécuter la requête. Pour SQLite, vous pouvez activer cette fonctionnalité en ajoutant EXPLAIN QUERY PLAN devant un SELECT déclaration :

>>>
>>> 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=?)')]

Cette requête tente de répertorier le prénom, le titre de l'article, le prix d'origine et le prix d'achat pour tous les articles achetés.

Voici à quoi ressemble le plan de requête :

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=?)

Notez que l'instruction fetch dans votre code Python ne renvoie que l'explication, mais pas les résultats. C'est parce que EXPLAIN QUERY PLAN n'est pas destiné à être utilisé en production.




Questions sur les bases de données non relationnelles

Dans la section précédente, vous avez présenté les différences entre les bases de données relationnelles et non relationnelles et utilisé SQLite avec Python. Maintenant, vous allez vous concentrer sur NoSQL. Votre objectif est de mettre en évidence ses points forts, ses différences et ses cas d'utilisation.


Un exemple MongoDB

Vous utiliserez les mêmes données qu'auparavant, mais cette fois votre base de données sera MongoDB. Cette base de données NoSQL est basée sur des documents et évolue très bien. Tout d'abord, vous devez installer la bibliothèque Python requise :

$ pip install pymongo

Vous pouvez également installer la communauté MongoDB Compass. Il comprend un IDE local parfait pour visualiser la base de données. Avec lui, vous pouvez voir les enregistrements créés, créer des déclencheurs et agir en tant qu'administrateur visuel pour la base de données.

Remarque : Pour exécuter le code de cette section, vous aurez besoin d'un serveur de base de données en cours d'exécution. Pour en savoir plus sur la configuration, consultez Introduction à MongoDB et Python.

Voici comment créer la base de données et insérer des données :

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)

Comme vous l'avez peut-être remarqué, MongoDB stocke les enregistrements de données dans des collections , qui sont l'équivalent d'une liste de dictionnaires en Python. En pratique, MongoDB stocke les documents BSON.



Q5 :Interroger des données avec MongoDB

Essayons de répliquer le BoughtItem table d'abord, comme vous l'avez fait dans SQL. Pour ce faire, vous devez ajouter un nouveau champ à un client. La documentation de MongoDB précise que l'opérateur de mot-clé set peut être utilisé pour mettre à jour un enregistrement sans avoir à écrire tous les champs existants :

# 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
                    }
                ]
            },
        }
    )

Remarquez comment vous avez ajouté des champs supplémentaires au customer sans définir explicitement le schéma au préalable. Génial !

En fait, vous pouvez mettre à jour un autre client avec un schéma légèrement modifié :

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

Semblables à SQL, les bases de données basées sur des documents permettent également d'exécuter des requêtes et des agrégations. Cependant, la fonctionnalité peut différer à la fois syntaxiquement et dans l'exécution sous-jacente. En fait, vous avez peut-être remarqué que MongoDB réserve le $ caractère pour spécifier une commande ou une agrégation sur les enregistrements, comme $group . Vous pouvez en savoir plus sur ce comportement dans la documentation officielle.

Vous pouvez effectuer des requêtes comme vous l'avez fait dans SQL. Pour commencer, vous pouvez créer un index :

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

Ceci est facultatif, mais cela accélère les requêtes qui nécessitent des recherches de noms.

Ensuite, vous pouvez récupérer les noms des clients triés par ordre croissant :

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

Vous pouvez également parcourir et imprimer les articles achetés :

>>>
>>> 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}]

Vous pouvez même récupérer une liste de noms uniques dans la base de données :

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

Maintenant que vous connaissez les noms des clients de votre base de données, vous pouvez créer une requête pour récupérer des informations à leur sujet :

>>>
>>> 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}]}

Voici la requête SQL équivalente :

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

Notez que même si la syntaxe ne diffère que légèrement, il existe une différence radicale dans la manière dont les requêtes sont exécutées sous le capot. Il faut s'y attendre en raison des différentes structures de requête et des cas d'utilisation entre les bases de données SQL et NoSQL.



Q6 :NoSQL contre SQL

Si vous avez un schéma en constante évolution, tel que des informations réglementaires financières, NoSQL peut modifier les enregistrements et imbriquer les informations associées. Imaginez le nombre de jointures que vous auriez à faire en SQL si vous aviez huit ordres d'imbrication ! Cependant, cette situation est plus courante que vous ne le pensez.

Maintenant, que se passe-t-il si vous souhaitez exécuter des rapports, extraire des informations sur ces données financières et en déduire des conclusions ? Dans ce cas, vous devez exécuter des requêtes complexes, et SQL a tendance à être plus rapide à cet égard.

Remarque : Les bases de données SQL, en particulier PostgreSQL, ont également publié une fonctionnalité qui permet d'insérer des données JSON interrogeables dans le cadre d'un enregistrement. Bien que cela puisse combiner le meilleur des deux mondes, la vitesse peut être préoccupante.

Il est plus rapide d'interroger des données non structurées à partir d'une base de données NoSQL que d'interroger des champs JSON à partir d'une colonne de type JSON dans PostgreSQL. Vous pouvez toujours faire un test de comparaison de vitesse pour une réponse définitive.

Néanmoins, cette fonctionnalité peut réduire le besoin d'une base de données supplémentaire. Parfois, les objets picklés ou sérialisés sont stockés dans des enregistrements sous forme de types binaires, puis désérialisés lors de la lecture.

La vitesse n'est pas la seule mesure, cependant. Vous voudrez également prendre en compte des éléments tels que les transactions, l'atomicité, la durabilité et l'évolutivité. Transactions sont importantes dans les applications financières, et ces fonctionnalités ont la priorité.

Comme il existe un large éventail de bases de données, chacune avec ses propres fonctionnalités, c'est le travail de l'ingénieur de données de prendre une décision éclairée sur la base de données à utiliser dans chaque application. Pour plus d'informations, vous pouvez lire les propriétés ACID relatives aux transactions de base de données.

Il se peut également qu'on vous demande quelles autres bases de données vous connaissez lors de votre entretien avec l'ingénieur de données. Il existe plusieurs autres bases de données pertinentes utilisées par de nombreuses entreprises :

  • Recherche élastique est très efficace dans la recherche de texte. Il exploite sa base de données documentaire pour créer un puissant outil de recherche.
  • Newt DB combine ZODB et la fonctionnalité PostgreSQL JSONB pour créer une base de données NoSQL compatible avec Python.
  • InfluxDB est utilisé dans les applications de séries chronologiques pour stocker des événements.

La liste est longue, mais cela illustre comment une grande variété de bases de données disponibles répondent toutes à leur industrie de niche.




Questions sur les bases de données de cache

Bases de données de cache contenir des données fréquemment consultées. Ils cohabitent avec les principales bases de données SQL et NoSQL. Leur objectif est d'alléger la charge et de traiter les demandes plus rapidement.


Un exemple Redis

Vous avez couvert les bases de données SQL et NoSQL pour les solutions de stockage à long terme, mais qu'en est-il d'un stockage plus rapide et plus immédiat ? Comment un ingénieur de données peut-il changer la vitesse à laquelle les données sont extraites d'une base de données ?

Les applications Web typiques récupèrent très souvent des données couramment utilisées, comme le profil ou le nom d'un utilisateur. Si toutes les données sont contenues dans une seule base de données, alors le nombre de hits le serveur de base de données obtient va être exagéré et inutile. En tant que tel, une solution de stockage plus rapide et plus immédiate est nécessaire.

Bien que cela réduise la charge du serveur, cela crée également deux maux de tête pour l'ingénieur de données, l'équipe backend et l'équipe DevOps. Tout d'abord, vous aurez maintenant besoin d'une base de données dont le temps de lecture est plus rapide que votre base de données SQL ou NoSQL principale. Cependant, le contenu des deux bases de données doit éventuellement correspondre. (Bienvenue dans le problème de la cohérence des états entre bases de données ! Amusez-vous.)

Le deuxième casse-tête est que DevOps doit maintenant se soucier de l'évolutivité, de la redondance, etc. pour la nouvelle base de données de cache. Dans la section suivante, vous vous plongerez dans des problèmes comme ceux-ci avec l'aide de Redis.



Q7 :Comment utiliser les bases de données de cache

Vous avez peut-être obtenu suffisamment d'informations dans l'introduction pour répondre à cette question ! Une base de données de cache est une solution de stockage rapide utilisée pour stocker des données éphémères, structurées ou non structurées. Il peut être partitionné et mis à l'échelle en fonction de vos besoins, mais sa taille est généralement beaucoup plus petite que votre base de données principale. Pour cette raison, votre base de données de cache peut résider en mémoire, ce qui vous permet de contourner le besoin de lire à partir d'un disque.

Remarque : Si vous avez déjà utilisé des dictionnaires en Python, alors Redis suit la même structure. C'est un magasin clé-valeur, où vous pouvez SET et GET des données comme un Python dict .

Lorsqu'une requête arrive, vous vérifiez d'abord la base de données de cache, puis la base de données principale. De cette façon, vous pouvez empêcher toute requête inutile et répétitive d'atteindre le serveur de la base de données principale. Comme une base de données de cache a un temps de lecture inférieur, vous bénéficiez également d'une augmentation des performances !

Vous pouvez utiliser pip pour installer la bibliothèque requise :

$ pip install redis

Maintenant, envisagez une demande pour obtenir le nom de l'utilisateur à partir de son ID :

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

Ce code vérifie si le nom est dans Redis en utilisant le id clé. Si ce n'est pas le cas, le nom est défini avec un délai d'expiration, que vous utilisez car le cache est de courte durée.

Maintenant, que se passe-t-il si votre interlocuteur vous demande ce qui ne va pas avec ce code ? Votre réponse devrait être qu'il n'y a pas de gestion des exceptions ! Les bases de données peuvent avoir de nombreux problèmes, comme des connexions interrompues, c'est donc toujours une bonne idée d'essayer d'attraper ces exceptions.




Questions sur les modèles de conception et les concepts ETL

Dans les grandes applications, vous utiliserez souvent plus d'un type de base de données. En fait, il est possible d'utiliser PostgreSQL, MongoDB et Redis dans une seule application ! Un problème difficile concerne les changements d'état entre les bases de données, ce qui expose le développeur à des problèmes de cohérence. Considérez le scénario suivant :

  1. Une valeur dans la base de données #1 est mis à jour.
  2. Cette même valeur dans la base de données #2 est conservée (non mise à jour).
  3. Une requête est exécuté sur la base de données #2.

Maintenant, vous avez un résultat incohérent et obsolète ! Les résultats renvoyés par la deuxième base de données ne refléteront pas la valeur mise à jour dans la première. Cela peut se produire avec deux bases de données, mais c'est particulièrement courant lorsque la base de données principale est une base de données NoSQL et que les informations sont transformées en SQL à des fins de requête.

Les bases de données peuvent avoir des travailleurs de fond pour résoudre ces problèmes. Ces travailleurs extraient données d'une base de données, transformez d'une manière ou d'une autre, et chargez dans la base de données cible. Lorsque vous convertissez une base de données NoSQL en une base SQL, le processus d'extraction, de transformation et de chargement (ETL) suit les étapes suivantes :

  1. Extrait : Il y a un déclencheur MongoDB chaque fois qu'un enregistrement est créé, mis à jour, etc. Une fonction de rappel est appelée de manière asynchrone sur un thread séparé.
  2. Transformer : Des parties de l'enregistrement sont extraites, normalisées et placées dans la structure de données (ou ligne) appropriée pour être insérées dans SQL.
  3. Charger : La base de données SQL est mise à jour par lots ou sous la forme d'un enregistrement unique pour les écritures à volume élevé.

Ce flux de travail est assez courant dans les applications financières, de jeu et de reporting. Dans ces cas, le schéma en constante évolution nécessite une base de données NoSQL, mais les rapports, l'analyse et les agrégations nécessitent une base de données SQL.


Q8 :Défis ETL

Il existe plusieurs concepts complexes dans ETL, notamment les suivants :

  • Mégadonnées
  • Problèmes avec état
  • Travailleurs asynchrones
  • Correspondance de type

La liste continue! Cependant, étant donné que les étapes du processus ETL sont bien définies et logiques, les ingénieurs de données et de backend se préoccupent généralement davantage des performances et de la disponibilité que de la mise en œuvre.

Si votre application écrit des milliers d'enregistrements par seconde dans MongoDB, votre travailleur ETL doit suivre la transformation, le chargement et la livraison des données à l'utilisateur dans le formulaire demandé. La vitesse et la latence peuvent devenir un problème, de sorte que ces travailleurs sont généralement écrits dans des langages rapides. Vous pouvez utiliser du code compilé pour l'étape de transformation pour accélérer les choses, car cette partie est généralement liée au processeur.

Remarque : Le traitement multiple et la séparation des travailleurs sont d'autres solutions que vous pourriez envisager.

Si vous avez affaire à de nombreuses fonctions gourmandes en ressources processeur, vous voudrez peut-être consulter Numba. Cette bibliothèque compile des fonctions pour les rendre plus rapides à l'exécution. Mieux encore, cela est facilement implémenté en Python, bien qu'il existe certaines limitations sur les fonctions pouvant être utilisées dans ces fonctions compilées.



Q9 :Modèles de conception dans le Big Data

Imaginez qu'Amazon doive créer un système de recommandation proposer des produits adaptés aux utilisateurs. L'équipe de science des données a besoin de données et de beaucoup de données ! Ils s'adressent à vous, l'ingénieur de données, et vous demandent de créer un entrepôt de base de données intermédiaire distinct. C'est là qu'ils nettoieront et transformeront les données.

Vous pourriez être choqué de recevoir une telle demande. Lorsque vous avez des téraoctets de données, vous aurez besoin de plusieurs machines pour gérer toutes ces informations. Une fonction d'agrégation de base de données peut être une opération très complexe. Comment interroger, agréger et exploiter efficacement des données relativement volumineuses ?

Apache avait initialement introduit MapReduce, qui suit la méthode map, shuffle, reduce flux de travail. L'idée est de mapper différentes données sur des machines distinctes, également appelées clusters. Ensuite, vous pouvez effectuer un travail sur les données, regroupées par clé, et enfin, agréger les données dans l'étape finale.

Ce flux de travail est encore utilisé aujourd'hui, mais il s'est récemment estompé au profit de Spark. Le modèle de conception, cependant, constitue la base de la plupart des flux de travail Big Data et est un concept très intrigant. Vous pouvez en savoir plus sur MapReduce sur IBM Analytics.



Q10 :Aspects communs du processus ETL et des workflows Big Data

Vous pourriez penser que c'est une question plutôt étrange, mais il s'agit simplement d'une vérification de vos connaissances en informatique, ainsi que de vos connaissances et de votre expérience globales en matière de conception.

Les deux flux de travail suivent le Producteur-Consommateur modèle. Un travailleur (le producteur) produit des données d'un certain type et les envoie à un pipeline. Ce pipeline peut prendre plusieurs formes, notamment des messages réseau et des déclencheurs. Une fois que le producteur a produit les données, le consommateur les consomme et les utilise. Ces travailleurs travaillent généralement de manière asynchrone et sont exécutés dans des processus distincts.

Vous pouvez comparer le producteur aux étapes d'extraction et de transformation du processus ETL. De même, dans le Big Data, le mapper peut être considéré comme le producteur, tandis que le réducteur est effectivement le Consommateur. Cette séparation des préoccupations est extrêmement importante et efficace dans le développement et la conception de l'architecture des applications.




Conclusion

Toutes nos félicitations! Vous avez couvert beaucoup de terrain et répondu à plusieurs questions d'entretien avec des ingénieurs de données. Vous en savez maintenant un peu plus sur les nombreuses casquettes qu'un ingénieur de données peut porter, ainsi que sur vos responsabilités en matière de bases de données, de conception et de flux de travail.

Fort de ces connaissances, vous pouvez désormais :

  • Utiliser Python avec des bases de données SQL, NoSQL et de cache
  • Utiliser Python dans ETL et interroger les applications
  • Planifier les projets à l'avance, en gardant à l'esprit la conception et le flux de travail

Bien que les questions d'entrevue puissent être variées, vous avez été exposé à plusieurs sujets et appris à sortir des sentiers battus dans de nombreux domaines différents de l'informatique. Vous êtes maintenant prêt à avoir une interview géniale !