mybatis nested select против вложенных результатов - PullRequest
0 голосов
/ 11 января 2019

Я младший пользователь mybatis, мне интересно, чем отличается вложенные select и вложенные результаты , просто ли это просто разница между подзапросом против присоединиться , особенно в производительности. Или это сделает некоторую оптимизацию?

Я использовал версию mybatis 3.4.7 и Oracle Oracle.

вот пример для справки:

private List<Post> posts;


    <resultMap id="blogResult" type="Blog">
        <collection property="posts" javaType="ArrayList" column="id" 
        ofType="Post" select="selectPostsForBlog"/>
    </resultMap>
    <select id="selectBlog" resultMap="blogResult">
        SELECT * FROM BLOG WHERE ID = #{id}
    </select>
    <select id="selectPostsForBlog" resultType="Post">
        SELECT * FROM POST WHERE BLOG_ID = #{id}
    </select>  


или


    <select id="selectBlog" resultMap="blogResult">
        select
        B.id as blog_id,
        B.title as blog_title,
        B.author_id as blog_author_id,
        P.id as post_id,
        P.subject as post_subject,
      P.body as post_body,
      from Blog B
      left outer join Post P on B.id = P.blog_id
      where B.id = #{id}
    </select>

    <resultMap id="blogResult" type="Blog">
        <id property="id" column="blog_id" />
        <result property="title" column="blog_title"/>
        <collection property="posts" ofType="Post">
        <id property="id" column="post_id"/>
        <result property="subject" column="post_subject"/>
        <result property="body" column="post_body"/>
      </collection>
    </resultMap>

если во вложенном выборе все еще есть проблема N + 1 как подзапрос?

У вас есть какой-нибудь совет или опыт, который лучше работает в определенных условиях или условиях? Большое спасибо:).

1 Ответ

0 голосов
/ 11 января 2019

Прежде всего, небольшое замечание по терминологии. Подзапрос в SQL является частью запроса, который сам по себе является запросом, например:

SELECT ProductName
  FROM Product 
WHERE Id IN (SELECT ProductId 
            FROM OrderItem
           WHERE Quantity > 100)

В этом случае следующий фрагмент запроса является подзапросом:

SELECT ProductId 
 FROM OrderItem
WHERE Quantity > 100

Таким образом, вы используете термин "подзапрос" здесь неправильно. В документации mybatis используется термин вложенный выбор .

Есть два способа получить связанные объекты / коллекции в mybatis. Вот соответствующая часть документации :

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

Когда используется вложенный выбор, mybatis сначала выполняет основной запрос (в вашем случае selectBlog), а затем для каждой записи выполняет другой выбор (отсюда и имя nested select), чтобы выбрать связанные Post сущности.

Когда используется Nested results, выполняется только один запрос, но к нему уже присоединены данные ассоциации. Таким образом, mybatis отображает результат на структуру объекта.

В вашем примере возвращается одна сущность Blog, поэтому при использовании nested select выполняются два запроса, но в общем случае (если вы получите список Blog s) вы столкнетесь с проблемой N+1.

Теперь давайте разберемся с производительностью. Все нижеприведенное предполагает, что запросы настроены (так как нет отсутствующих индексов), вы используете пул соединений, база данных размещена, в сущности говоря, ваша система настроена во всех других отношениях.

Говоря о спектакле, единого правильного ответа не существует, и вы можете различаться. Вам всегда нужно тестировать ваши конкретные рабочие процессы в вашей настройке. Учитывая, что на производительность влияют многие факторы, такие как распределение данных (например, максимальные / минимальные / arg сообщения в каждом блоге), размер записи в БД (например, количество и размер полей данных в блоге и записи), параметры БД ( например, тип диска и скорость, объем памяти, доступной для кэширования набора данных и т. д.) может не быть единственного ответа, только некоторые общие наблюдения, которые следуют.

Но мы можем понять разницу в производительности, если мы посмотрим на случаи на концах спектра производительности. Хотелось бы увидеть случаи, когда nested select значительно опережает join и наоборот.

Для извлечения коллекции соединение должно быть лучше в большинстве случаев, потому что задержка в сети для выполнения N+1 количества запросов.

Один случай, когда nested select может быть лучше, связан с взаимно однозначным сопоставлением, когда запись в основной таблице ссылается на какую-то другую таблицу, а количество элементов в другой таблице невелико, а размер записи в другой таблице большой.

Например, давайте рассмотрим Blog, обладающее свойством category, которое ссылается на таблицу categories, и может иметь одно из этих значений Science, Fashion, News. И давайте представим, что список блогов выбирается каким-то фильтром, например, ключевыми словами в заголовке блога. Если результат содержит, скажем, 500 элементов, то большинство связанных категорий будут дубликатами.

Если мы выберем их с помощью join, каждая запись в наборе результатов будет содержать Category полей данных (и в качестве напоминания большинство из них являются дубликатами, и у нас есть много данных в записи Category).

Если мы выберем их с помощью вложенного выбора, мы сделаем запрос для выборки категории по идентификатору категории для каждой записи, и здесь кеш mybatis сеанса начинает работать. В течение SqlSession каждый раз, когда mybatis выполняет запрос, он сохраняет свой результат в кеше сеанса, поэтому он не выполняет повторяющиеся запросы к базе данных, а извлекает их из кеша. Это означает, что после того, как mybatis получит некоторую категорию по идентификатору для первой записи, он будет использовать ее для всех других записей в наборе записей, который он обрабатывает.

В приведенном выше примере мы выполняем до 4 запросов к базе данных, но уменьшенный объем данных, передаваемых по сети, может перевесить необходимость выполнения 4 запросов.

...