В по сравнению с Соединением с большими наборами строк

Получите QueryString в Spring MVC Controller

Это решение для портала Liferay, и оно работает.

Пример строки запроса: ?reportTypeId=1&reportSeqNo=391

Чтобы получить значение reportSeqNo в Liferay Portal, нам нужно получить оригинальный запрос сервлета.

String reportSeq = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(renderRequest)).getParameter("reportSeqNo");
28
задан macleojw 16 June 2009 в 14:07
поделиться

12 ответов

Update:

This article in my blog summarizes both my answer and my comments to another answers, and shows actual execution plans:


SELECT  *
FROM    a
WHERE   a.c IN (SELECT d FROM b)

SELECT  a.*
FROM    a
JOIN    b
ON      a.c = b.d

These queries are not equivalent. They can yield different results if your table b is not key preserved (i. e. the values of b.d are not unique).

The equivalent of the first query is the following:

SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT d
        FROM    b
        ) bo
ON      a.c = bo.d

If b.d is UNIQUE and marked as such (with a UNIQUE INDEX or UNIQUE CONSTRAINT), then these queries are identical and most probably will use identical plans, since SQL Server is smart enough to take this into account.

SQL Server can employ one of the following methods to run this query:

  • If there is an index on a.c, d is UNIQUE and b is relatively small compared to a, then the condition is propagated into the subquery and the plain INNER JOIN is used (with b leading)

  • If there is an index on b.d and d is not UNIQUE, then the condition is also propagated and LEFT SEMI JOIN is used. It can also be used for the condition above.

  • If there is an index on both b.d and a.c and they are large, then MERGE SEMI JOIN is used

  • If there is no index on any table, then a hash table is built on b and HASH SEMI JOIN is used.

Neither of these methods reevaluates the whole subquery each time.

See this entry in my blog for more detail on how this works:

There are links for all RDBMS's of the big four.

30
ответ дан 28 November 2019 в 03:15
поделиться

Ни то, ни другое. Используйте ANSI-92 JOIN:

SELECT a.*
FROM a JOIN b a.c = b.d

Однако лучше всего как EXISTS

SELECT a.*
FROM a
WHERE EXISTS (SELECT * FROM b WHERE a.c = b.d)

Это удаляет дубликаты, которые могут быть сгенерированы JOIN, но работает так же быстро, если не быстрее

5
ответ дан 28 November 2019 в 03:15
поделиться

IN оценивается (и повторно запускается выбор из b) для каждой строки в a, тогда как JOIN оптимизирован для использования индексов и других изящных уловок разбиения на страницы ...

In тем не менее, в большинстве случаев оптимизатор, вероятно, сможет построить JOIN из коррелированного подзапроса и в любом случае будет иметь тот же план выполнения.

Изменить: Пожалуйста, прочтите комментарии ниже для дальнейшего ... обсуждения действительности этот ответ и фактический ответ на вопрос ОП. =)

4
ответ дан 28 November 2019 в 03:15
поделиться

] Я бы сказал, не считая того, чтобы протестировать его на большом количестве тестовых данных, используя JOINS. У меня всегда была лучшая производительность при их использовании в большинстве случаев по сравнению с подзапросом IN, и у вас есть гораздо больше вариантов настройки в отношении того, как присоединиться, что выбрано, что нет и т. Д.

2
ответ дан 28 November 2019 в 03:15
поделиться

Исходя из опыта работы с таблицей с 49 000 000 строк, я бы порекомендовал LEFT OUTER JOIN. Использование IN или EXISTS На завершение ушло 5 минут, где LEFT OUTER JOIN завершается за 1 секунду.

SELECT a.*
FROM a LEFT OUTER JOIN b ON a.c = b.d
WHERE b.d is not null -- Given b.d is a primary Key with index

На самом деле в моем запросе я делаю это для 9 таблиц.

4
ответ дан 28 November 2019 в 03:15
поделиться

Это разные запросы с разными результатами. С запросом IN вы получите 1 строку из таблицы «a» всякий раз, когда совпадет предикат. С запросом INNER JOIN вы будете получать a * b строк всякий раз, когда будет выполнено условие соединения. Таким образом, со значениями в a из {1,2,3} и b из {1,2,2,3} вы получите 1,2,2,3 из JOIN и 1,2,3 из IN.

РЕДАКТИРОВАТЬ - я думаю, вы можете найти здесь несколько ответов, которые создадут неправильное представление. Попробуйте сами, и вы увидите, что это все прекрасные планы запроса:

create table t1 (t1id int primary key clustered)
create table t2 (t2id int identity primary key clustered
    ,t1id int references t1(t1id)
)


insert t1 values (1)
insert t1 values (2)
insert t1 values (3)
insert t1 values (4)
insert t1 values (5)

insert t2 values (1)
insert t2 values (2)
insert t2 values (2)
insert t2 values (3)
insert t2 values (4)


select * from t1 where t1id in (select t1id from t2)
select * from t1 where exists (select 1 from t2 where t2.t1id = t1.t1id)
select t1.* from t1 join t2 on t1.t1id = t2.t1id

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

2
ответ дан 28 November 2019 в 03:15
поделиться

From MSDN documentation on Subquery Fundamentals:

Many Transact-SQL statements that включать подзапросы можно альтернативно формулируется как объединение. Остальные вопросы можно задавать только с подзапросы. В Transact-SQL есть обычно нет разницы в производительности между утверждением, которое включает подзапрос и семантически эквивалент версия, которой нет. Однако в некоторые случаи, когда существование должно быть проверен, соединение дает лучше производительность. В противном случае вложенные запрос должен обрабатываться для каждого результат внешнего запроса для обеспечения устранение дубликатов. В таком случаях, объединенный подход даст better results.

In the example you've provided, the nested query need only be processed a single time for each of the outer query results, so there should be no performance difference. Checking the execution plans for both queries should confirm this.

Note: Though the question itself didn't specify SQL Server 2005, I answered with that assumption based on the question tags. Other database engines (even different SQL Server versions) may not optimize in the same way.

2
ответ дан 28 November 2019 в 03:15
поделиться

Observe the execution plan for both types and draw your conclusions. Unless the number of records returned by the subquery in the "IN" statement is very small, the IN variant is almost certainly slower.

1
ответ дан 28 November 2019 в 03:15
поделиться

Я бы использовал соединение, держу пари, что оно будет намного быстрее, чем IN. Это, конечно, предполагает наличие определенных первичных ключей, что позволяет значительно ускорить процесс индексирования.

0
ответ дан 28 November 2019 в 03:15
поделиться

Обычно считается, что соединение будет более эффективным, чем подзапрос IN; однако оптимизатор SQL * Server обычно не дает заметной разницы в производительности. Даже в этом случае, вероятно, лучше всего кодировать с использованием условия соединения, чтобы поддерживать согласованность ваших стандартов. Кроме того, если ваши данные и код когда-либо потребуется перенести в будущем, механизм базы данных может оказаться не таким снисходительным (например, использование соединения вместо подзапроса IN имеет огромное значение в MySql).

0
ответ дан 28 November 2019 в 03:15
поделиться

Теория пока поможет вам только в подобных вопросах. В конце концов, вы захотите протестировать оба запроса и посмотреть, какой из них действительно работает быстрее. У меня были случаи, когда версия JOIN занимала больше минуты, а версия IN - меньше секунды. У меня также были случаи, когда JOIN был на самом деле быстрее.

Лично я предпочитаю начинать с версии IN, если знаю, что мне не понадобятся поля из таблицы подзапросов. Если это начинает работать медленно, я оптимизирую. К счастью, для больших наборов данных переписывание запроса имеет такое существенное значение, что вы можете просто рассчитать его время из Query Analyzer и знать, что вы делаете успехи.

Удачи!

0
ответ дан 28 November 2019 в 03:15
поделиться

Я всегда был сторонником методологии IN. Эта ссылка содержит подробную информацию о тесте, проведенном в PostgresSQL. http://archives.postgresql.org/pgsql-performance/2005-02/msg00327.php

0
ответ дан 28 November 2019 в 03:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: