Sobes.tech
Middle

Какъв е проблемът с пробата n+1?

sobes.tech AI

Отговор от AI

Това е проблем с производителността при работа с бази данни, когато за получаване на свързани данни са необходими N+1 заявки вместо една.

Настъпва, когато:

  1. Изпълнява се една заявка за получаване на списък с основните същности.
  2. След това за всяка от тези същности се изпълнява отделна заявка за получаване на свързаните дъщерни същности.

Пример в JPA:

// Получаване на списък с потребители
List<User> users = userRepository.findAll();

// За всеки потребител получаване на поръчките му
for (User user : users) {
    List<Order> orders = user.getOrders(); // Извиква N заявки към базата данни, една за всеки потребител
}

Решение: Използване на заявки с зареждане на свързаните данни наведнъж:

  1. JOIN FETCH: Зареждане на свързаните същности заедно с основната в една заявка.

    // Пример с JPQL
    List<User> users = entityManager.createQuery("SELECT u FROM User u JOIN FETCH u.orders", User.class).getResultList();
    
  2. EntityGraph: Деклариране на граф на същности, за да се посочи кои свързани обекти трябва да бъдат заредени.

    // На ниво същност
    @Entity
    @NamedEntityGraph(name = "User.orders", attributeNodes = @NamedAttributeNode("orders"))
    public class User {
        // ...
    }
    
    // Използване в репозитория
    @Query("SELECT u FROM User u")
    @EntityGraph(value = "User.orders")
    List<User> findAllWithOrders();
    
  3. Batch Fetching: Зареждане на свързаните обекти на партиди (ORM може да го направи на заден план с подходяща конфигурация).

Решаването на проблема N+1 значително подобрява производителността на приложенията, като намалява броя на заявките към базата данни.