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

Améliorer les performances du backend Partie 2/3 :Utiliser les index de base de données

Les index de base de données sont une préoccupation des développeurs. Ils ont le potentiel d'améliorer les performances des fonctionnalités de recherche et de filtrage qui utilisent une requête SQL dans le backend. Dans la deuxième partie de cette série d'articles, je montrerai l'impact d'un index de base de données sur l'accélération des filtres à l'aide d'une application Web Java développée avec Spring Boot et Vaadin.

Lisez la partie 1 de cette série si vous voulez savoir comment fonctionne l'exemple d'application que nous allons utiliser ici. Vous pouvez trouver le code sur GitHub. Aussi, et si vous préférez, j'ai enregistré une version vidéo de cet article :

L'exigence

Nous avons une page Web avec une grille qui affiche une liste de livres d'une base de données MariaDB :

Nous voulons ajouter un filtre pour permettre aux utilisateurs de cette page de voir quels livres ont été publiés à une date donnée.

 Mise en œuvre de la requête et du service de référentiel

Nous devons apporter quelques modifications au backend pour prendre en charge le filtrage des données à la date de publication. Dans la classe du référentiel, nous pouvons ajouter la méthode suivante :

@Repository
public interface BookRepository extends JpaRepository<Book, Integer> {

    Page<Book> findByPublishDate(LocalDate publishDate, Pageable pageable);

}

Cela utilise le chargement différé comme nous l'avons vu dans la partie 1 de cette série d'articles. Nous n'avons pas à implémenter cette méthode - Spring Data la créera pour nous au moment de l'exécution.

Nous devons également ajouter une nouvelle méthode à la classe de service (qui est la classe que l'interface utilisateur utilise pour exécuter la logique métier). Voici comment:

@Service
public class BookService {

    private final BookRepository repository;

    ...

    public Stream<Book> findAll(LocalDate publishDate, int page, int pageSize) {
        return repository.findByPublishDate(publishDate, PageRequest.of(page, pageSize)).stream();
    }

}

Ajouter un filtre à la page Web

Avec le backend prenant en charge le filtrage des livres par date de publication, nous pouvons ajouter un sélecteur de date à la mise en œuvre de la page Web (ou de la vue) :

@Route("")
public class BooksView extends VerticalLayout {

    public BooksView(BookService service) {

        ...

        var filter = new DatePicker("Filter by publish date");
        filter.addValueChangeListener(event ->
                grid.setItems(query ->
                        service.findAll(filter.getValue(), query.getPage(), query.getPageSize())
                )
        );

        add(filter, grid);
        setSizeFull();
    }

    ...
}

Ce code crée simplement un nouveau DatePicker objet qui écoute les changements de sa valeur (via un écouteur de changement de valeur). Lorsque la valeur change, nous utilisons la classe de service pour obtenir les livres publiés à la date sélectionnée par l'utilisateur. Les livres correspondants sont ensuite définis comme éléments de la Grid .

Tester la requête lente

Nous avons implémenté le filtre; cependant, il est extrêmement lent si vous avez, par exemple, 200 000 lignes dans la table. Essayez-le ! J'ai écrit un article qui explique comment générer des données de démonstration réalistes pour les applications Java. Avec ce nombre de lignes, l'application a mis plusieurs secondes à afficher les données sur la page Web de ma machine (MacBook Pro 2,3 GHz Quad-Core Intel Core i5). Cela ruine complètement l'expérience utilisateur.

Analyser les requêtes avec "Explain Query"

Si vous avez activé la journalisation des requêtes, vous pouvez trouver la requête générée par Hibernate dans le journal du serveur. Copiez-le, remplacez les points d'interrogation par des valeurs réelles et exécutez-le dans un client de base de données SQL. En fait, je peux vous faire gagner du temps. Voici une version simplifiée de la requête :

SELECT id, author, image_data, pages, publish_date, title
FROM book
WHERE publish_date = '2021-09-02';

MariaDB inclut le EXPLAIN instruction qui nous donne des informations utiles sur la façon dont le moteur estime que va exécuter la requête. Pour l'utiliser, il suffit d'ajouter EXPLAIN avant la requête :

EXPLAIN SELECT id, author, image_data, pages, publish_date, title
FROM book
WHERE publish_date = '2021-09-02';

Voici le résultat :

La documentation contient tout ce que vous devez savoir à ce sujet, mais le bit important est la valeur dans le type colonne :TOUS . Cette valeur nous indique que le moteur estime qu'il devra récupérer ou lire toutes les lignes de la table. Pas une bonne chose.

Créer un index

Heureusement, nous pouvons facilement résoudre ce problème en créant un index sur la colonne que nous utilisons pour filtrer les données :publish_date . Voici comment:

CREATE INDEX book\_publish\_date_index ON book(publish_date);

Un index de base de données est une structure de données créée par le moteur, généralement un b-tree (b pour équilibré ), et cela accélère le processus de recherche d'une certaine ligne dans une table, c'est-à-dire la recherche d'une ligne en fonction de la valeur dans la colonne sur laquelle l'index est construit. Le processus est plus rapide grâce à la nature des b-trees - ils conservent les données ordonnées en réduisant la complexité temporelle de O(N) à O(log(N)) et même O(log(1)) dans certains cas.

Tester l'amélioration

Avec l'index construit, nous pouvons exécuter à nouveau l'instruction EXPLAIN et voir que la colonne de type affiche la valeur ref au lieu de TOUS :

La réf signifie que le moteur utilisera l'index lorsque nous exécuterons la requête. Il est important de vérifier cela lorsque vous ajoutez des index à vos requêtes plus complexes. Utilisez toujours le EXPLAIN pour vérifier que vous gagnez en performance lorsque vous introduisez un index.

Si vous essayez l'application Web dans le navigateur et sélectionnez une autre date dans le sélecteur de date (pas besoin de redémarrer le serveur), vous verrez une énorme différence ! Par exemple, les données sont récupérées en moins d'une seconde sur ma machine contrairement à plusieurs secondes avant la création de l'index !