Рубрики
Без рубрики

Повышение производительности Серверной Части Часть 2/3: Использование Индексов базы данных

Индексы баз данных – это забота разработчиков. У них есть потенциал для повышения производительности… С тегами sql, java, база данных, mariadb.

Повышение Производительности Серверной Части (Серия Из 3 Частей)

Индексы баз данных – это забота разработчиков. У них есть потенциал для повышения производительности функций поиска и фильтрации, которые используют SQL-запрос в серверной части. Во второй части этой серии статей я покажу влияние индекса базы данных на ускорение фильтров с помощью веб-приложения Java, разработанного с помощью Spring Boot и Ваадин .

Прочитайте часть 1 этой серии , если вы хотите узнать, как работает пример приложения, которое мы будем использовать здесь. Вы можете найти код на GitHub . Кроме того, и если вы предпочитаете, я записал видеоверсию этой статьи:

Требование

У нас есть веб-страница с сеткой, которая показывает список книг из базы данных MariaDB :

Мы хотим добавить фильтр, позволяющий пользователям этой страницы видеть, какие книги были опубликованы на определенную дату.

Реализация запроса и службы репозитория

Мы должны внести некоторые изменения в серверную часть, чтобы поддерживать фильтрацию данных по дате публикации. В классе репозитория мы можем добавить следующий метод:

@Repository
public interface BookRepository extends JpaRepository {

    Page findByPublishDate(LocalDate publishDate, Pageable pageable);

}

При этом используется отложенная загрузка, как мы видели в части 1 этой серии статей. Нам не нужно реализовывать этот метод — Spring Data создаст его для нас во время выполнения.

Нам также необходимо добавить новый метод в класс обслуживания (который является классом, используемым пользовательским интерфейсом для запуска бизнес-логики). Вот как это делается:

@Service
public class BookService {

    private final BookRepository repository;

    ...

    public Stream 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 , который прослушивает изменения его значения (через valuechangelistener). При изменении значения мы используем класс обслуживания для публикации книг в дату, выбранную пользователем. Затем соответствующие книги устанавливаются в качестве элементов Сетки .

Тестирование медленного запроса

Мы внедрили фильтр, однако он работает крайне медленно, если у вас, например, 200 тысяч строк в таблице. Попробуй! Я написал статью , в которой объясняется, как создавать реалистичные демонстрационные данные для приложений Java. При таком количестве строк приложению потребовалось несколько секунд, чтобы отобразить данные на веб-странице на моем компьютере (MacBook Pro с четырехъядерным процессором Intel Core i5 с частотой 2,3 ГГц). Это полностью разрушает пользовательский интерфейс.

Анализ Запросов С Помощью Функции “Объяснить Запрос”

Если вы включили ведение журнала запросов, вы можете найти запрос, сгенерированный Hibernate, в журнале сервера. Скопируйте его, замените вопросительные знаки фактическими значениями и запустите его в клиенте базы данных SQL. На самом деле, я могу сэкономить вам немного времени. Вот упрощенная версия запроса:

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

MariaDB включает в себя инструкцию EXPLAIN , которая дает нам полезную информацию о том, как механизм оценивает, что собирается выполнить запрос. Чтобы использовать его, просто добавьте ОБЪЯСНИТЕ перед запросом:

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

Вот результат:

В документации есть все, что вам нужно знать об этом, но важным моментом является значение в столбце тип : ВСЕ . Это значение говорит нам о том, что, по оценкам механизма, ему придется извлекать или считывать все строки в таблице. Не очень хорошая вещь.

Создание индекса

К счастью, мы можем легко исправить это, создав индекс в столбце, который мы используем для фильтрации данных: дата публикации . Вот как это делается:

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

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

Тестирование улучшения

С построенным индексом мы можем снова запустить инструкцию EXPLAIN и увидеть, что в столбце тип отображается значение ref вместо ВСЕ :

Значение ref означает, что механизм будет использовать индекс при выполнении запроса. Важно, чтобы вы проверяли это при добавлении индексов в свои более сложные запросы. Всегда используйте инструкцию EXPLAIN , чтобы дважды проверить, повышается ли производительность при введении индекса.

Если вы попробуете веб-приложение в браузере и выберете другую дату в окне выбора даты (нет необходимости перезапускать сервер), вы увидите огромную разницу! Например, данные извлекаются на моей машине менее чем за секунду, в отличие от нескольких секунд до создания индекса!

Повышение Производительности Серверной Части (Серия Из 3 Частей)

Оригинал: “https://dev.to/alejandro_du/improving-backend-performance-part-23-using-database-indexes-3eih”