クエリN+1問題



1.問題の状況


クエリ
  • クエリされていない問題
  • クエリークエリー数による問題
  • 2.原因分析

  • FetchTypeはLazyに設定されているが、この設定は適用されていない
  • 遅延ロードが適用されていないドメインの関連付けを確認し、OneToOneが所有者でないことを確認します.
    Board Entity
    @OneToOne(mappedby = "board", fetch = FetchType.LAZY)
    private Vote vote;
    Vote Entity
    @OneToOne(fetch = FetchType.Lazy)
    @JoinColumn(name = "board_id")
    private Board board;
    @OneToOne(mappedby = "board"):BoardとVoteをOneToOneとして双方向関連付け(VoteはBoardのFKを含む)fetch = FetchType.LAZY:Boardは遅延ロードに設定されていますが、5つの取締役会を参照すると、同じ5回の票が得られます.ただし、Voteは所有者であるため、Voteで設定した遅延ロードは変更されないため、Boardはクエリされません.
    Query X 5
    Hibernate: 
        select
            vote0_.id as id1_15_1_,
            vote0_.board_id as board_id8_15_1_,
            vote0_.chat_room_id as chat_roo9_15_1_,
            vote0_.top_pointa as top_poin2_15_1_,
            vote0_.top_pointb as top_poin3_15_1_,
            vote0_.topicacnt as topicacn4_15_1_,
            vote0_.topicbcnt as topicbcn5_15_1_,
            vote0_.total_pointa as total_po6_15_1_,
            vote0_.total_pointb as total_po7_15_1_,
        from
            vote vote0_ 
        where
            vote0_.board_id=?

    3.対策案

  • OneToOneですが、OneToOneの場合は遅延ロードを使用できます.
  • getterにのみ書き込むエンティティを所有者に設定し、一方向関連
  • を確立する.
    Board Entity
    @OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
    @JoinColumn(name = "vote")
    private Vote vote;
    @JoinColumn(name = "vote"):BoardからVoteを要求する論理が必要であるため、Boardを所有者に設定fetch = FetchType.Lazy:Boardがマスターであるため、OneToOneには遅延ロード設定が適用されます.
    Query
    Hibernate: 
        select
            board0_.id as id1_1_,
            board0_.created_at as created_2_1_,
            board0_.modified_at as modified3_1_,
            board0_.converted_file_name as converte4_1_,
            board0_.file_path as file_pat5_1_,
            board0_.topic_a as topic_a6_1_,
            board0_.topic_b as topic_b7_1_,
            board0_.user_id as user_id9_1_,
            board0_.vote as vote10_1_,
            board0_.winner as winner8_1_ 
        from
            board board0_ 
        order by
            board0_.created_at desc limit ?

    4.その他の問題

  • 5 BoardリクエストVoteの場合、5つのVoteクエリの問題
  • が発生します.
  • pageが処理され、fetch joinで
  • を解決できません.
    Query X 5
    Hibernate: 
        select
            vote0_.id as id1_15_0_,
            vote0_.chat_room_id as chat_roo8_15_0_,
            vote0_.top_pointa as top_poin2_15_0_,
            vote0_.top_pointb as top_poin3_15_0_,
            vote0_.topicacnt as topicacn4_15_0_,
            vote0_.topicbcnt as topicbcn5_15_0_,
            vote0_.total_pointa as total_po6_15_0_,
            vote0_.total_pointb as total_po7_15_0_ 
        from
            vote vote0_ 
        where
            vote0_.id=?

    5.その他のトラブルシューティング


    batchsizeを
  • globalに設定すると、
  • が改善され、複数回のクエリでも1回のクエリしか発生しません.
    application.yml
    default_batch_fetch_size: 10
    Query X 1
    Hibernate: 
        select
            vote0_.id as id1_15_0_,
            vote0_.chat_room_id as chat_roo8_15_0_,
            vote0_.top_pointa as top_poin2_15_0_,
            vote0_.top_pointb as top_poin3_15_0_,
            vote0_.topicacnt as topicacn4_15_0_,
            vote0_.topicbcnt as topicbcn5_15_0_,
            vote0_.total_pointa as total_po6_15_0_,
            vote0_.total_pointb as total_po7_15_0_ 
        from
            vote vote0_ 
        where
            vote0_.id in (
                ?, ?, ?
            )