MariaDB
 sql >> база данни >  >> RDS >> MariaDB

Подобряване на производителността на бекенда, част 2/3:Използване на индекси на база данни

Индексите на бази данни са проблем на разработчиците. Те имат потенциала да подобрят производителността на функциите за търсене и филтриране, които използват SQL заявка в бекенда. Във втората част от тази поредица от статии ще покажа влиянието, което индексът на базата данни оказва при ускоряването на филтрите с помощта на уеб приложение на Java, разработено с Spring Boot и Vaadin.

Прочетете част 1 от тази серия, ако искате да научите как работи примерното приложение, което ще използваме тук. Можете да намерите кода на GitHub. Освен това, и ако предпочитате, записах видео версия на тази статия:

Изискването

Имаме уеб страница с решетка, която показва списък с книги от база данни на MariaDB:

Искаме да добавим филтър, за да позволим на потребителите на тази страница да виждат кои книги са публикувани на дадена дата.

Внедряване на заявката и услугата на хранилището

Трябва да направим някои промени в бекенда, за да поддържаме филтриране на данни до датата на публикуване. В класа на хранилището можем да добавим следния метод:

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

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

}

Това използва мързеливо зареждане, както видяхме в част 1 от тази серия статии. Не е нужно да прилагаме този метод — Spring Data ще го създаде за нас по време на изпълнение.

Също така трябва да добавим нов метод към класа на услугите (който е класът, който потребителският интерфейс използва за изпълнение на бизнес логиката). Ето как:

@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();
    }

}

Добавяне на филтър към уеб страницата

С бекенда, поддържащ филтриране на книги по дата на публикуване, можем да добавим инструмент за избор на дата към реализацията на уеб страницата (или преглед):

@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();
    }

    ...
}

Този код просто създава нов DatePicker обект, който слуша промени в стойността си (чрез слушател за промяна на стойност). Когато стойността се промени, ние използваме класа на услугата, за да публикуваме книгите на избраната от потребителя дата. След това съответстващите книги се задават като елементи от Grid .

Тестване на бавната заявка

Внедрихме филтъра; обаче е изключително бавно, ако имате например 200 хиляди реда в таблицата. Опитай! Написах статия, която обяснява как да генерирате реалистични демо данни за Java приложения. С този брой редове приложението отне няколко секунди, за да покаже данните на уеб страницата на моята машина (MacBook Pro 2,3 GHz четириядрен Intel Core i5). Това напълно разваля потребителското изживяване.

Анализиране на заявки с „Explain Query“

Ако сте активирали регистрирането на заявки, можете да намерите заявката, която е генерирана от Hibernate, в регистъра на сървъра. Копирайте го, заменете въпросителните знаци с действителни стойности и го стартирайте в клиент на SQL база данни. Всъщност мога да ви спестя малко време. Ето опростена версия на заявката:

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

MariaDB включва EXPLAIN изявление, което ни дава полезна информация за това как машината оценява, че ще изпълни заявката. За да го използвате, просто добавете EXPLAIN преди заявката:

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

Ето резултата:

Документацията съдържа всичко, което трябва да знаете за нея, но важната част е стойността в type колона:ВСИЧКИ . Тази стойност ни казва, че машината изчислява, че ще трябва да извлече или прочете всички редове в таблицата. Нещо добро.

Създаване на индекс

За щастие можем лесно да поправим това, като създадем индекс в колоната, която използваме за филтриране на данните:publish_date . Ето как:

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

Индексът на базата данни е структура от данни, създадена от машината, обикновено b-дърво (b за балансиран ), и това ускорява процеса на намиране на определен ред в таблица, тоест търсене на ред, като се има предвид стойността в колоната, върху която е изграден индексът. Процесът е по-бърз благодарение на естеството на b-дърветата – те поддържат подредените данни, намалявайки времевата сложност от O(N) до O(log(N)) и дори O(log(1)) в някои случаи.

Тестване на подобрението

С изградения индекс можем да изпълним отново оператора EXPLAIN и да видим, че колоната тип показва стойността ref вместо ВСИЧКИ :

Рефита value означава, че двигателят ще използва индекса, когато стартираме заявката. Важно е да проверявате това, когато добавяте индекси към по-сложните си заявки. Винаги използвайте EXPLAIN изявление, за да проверите отново дали получавате по-висока производителност, когато въвеждате индекс.

Ако опитате уеб приложението в браузъра и изберете друга дата в инструмента за избор на дата (няма нужда да рестартирате сървъра), ще видите огромна разлика! Например данните се извличат за по-малко от секунда на моята машина, за разлика от няколко секунди преди да създадем индекса!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Автоматизирано тестване на процеса на надстройка за MySQL/MariaDB/Percona сървър

  2. Как да разположите Open edX MySQL база данни за висока наличност

  3. Справяне с проблеми с репликацията на MySQL с помощта на ClusterControl

  4. Мигриране от MySQL Enterprise към MariaDB 10.3

  5. Как ADDDATE() работи в MariaDB