Sobes.tech
Middle

Mi az n+1 mintavételi probléma?

sobes.tech MI

Válasz az MI-től

Ez egy teljesítményprobléma adatbázisokkal való munkavégzés közben, amikor a kapcsolódó adatok lekéréséhez N+1 lekérdezés szükséges egy helyett.

Ez akkor fordul elő, amikor:

  1. Egy lekérdezést hajtanak végre a fő entitások listájának megszerzéséhez.
  2. Ezután minden egyes entitáshoz külön lekérdezést hajtanak végre a kapcsolódó gyermek entitások megszerzéséhez.

Példa JPA-ban:

// Felhasználók listájának lekérése
List<User> users = userRepository.findAll();

// Minden felhasználóhoz kérjük le a rendeléseit
for (User user : users) {
    List<Order> orders = user.getOrders(); // N lekérdezést hív meg az adatbázisban, egyet minden felhasználóhoz
}

Megoldás: Használjon olyan lekérdezéseket, amelyek egy lépésben betöltik a kapcsolódó adatokat:

  1. JOIN FETCH: A kapcsolódó entitások betöltése a fő entitással együtt egy lekérdezésben.

    // JPQL példával
    List<User> users = entityManager.createQuery("SELECT u FROM User u JOIN FETCH u.orders", User.class).getResultList();
    
  2. EntityGraph: Egy entitás gráfjának deklarálása, hogy megadja, mely kapcsolódó objektumokat kell betölteni.

    // Entitás szinten
    @Entity
    @NamedEntityGraph(name = "User.orders", attributeNodes = @NamedAttributeNode("orders"))
    public class User {
        // ...
    }
    
    // A repository-ban való használat
    @Query("SELECT u FROM User u")
    @EntityGraph(value = "User.orders")
    List<User> findAllWithOrders();
    
  3. Batch Fetching: A kapcsolódó objektumok csoportos betöltése (az ORM ezt háttérben, megfelelő konfigurációval megteheti).

A N+1 problémának a megoldása jelentősen javítja az alkalmazások teljesítményét, csökkentve az adatbázis-kérések számát.