Почему оператор IsEqual (=) работает быстрее, чем оператор IsNotEqual (<>) в Oracle? - PullRequest
5 голосов
/ 28 июля 2010

Как следует из названия, если у кого-то есть ответ, который я хотел бы знать.Я гуглил, но не смог найти прямой ответ.

Пример:

Это работает

SELECT COUNT(*) FROM Table1 TB1, Table2 TB2
WHERE TB1.Field1 = TB2.Table2 

Это, кажется, занимает часы

SELECT COUNT(*) FROM Table1 TB1, Table2 TB2
WHERE TB1.Field1 <> TB2.Table2 

Ответы [ 4 ]

12 голосов
/ 28 июля 2010

Потому что это разные SQL-предложения. В первой вы объединяете две таблицы, используя поля Field1 и Table2. Вероятно, возвращает несколько записей.

Во втором запросе, вероятно, возвращено много записей, так как вы выполняете перекрестное соединение, и множество строк удовлетворят вашему условию Field1 <> Table2.

Очень упрощенный пример

Table1

Field1
------
1
2
5
9

Table2

Table2
------
3
4
5
6
9

Query1 вернет 2, поскольку только 5 и 9 являются общими.

Query2 вернет 18, так как будет подсчитано много строк из перекрестного соединения.

Если у вас есть таблица с большим количеством записей, обработка вашего второго запроса займет некоторое время.

11 голосов
/ 28 июля 2010

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

Сравнение = можно преобразовать и оптимизировать так же, как и простое объединение двух полей. Это означает, что нормальные индексы могут использоваться для очень быстрого выполнения запроса, возможно, без чтения фактических данных и использования вместо них только индексов.

A <> Сравнение, с другой стороны, требует полного декартового произведения , которое обычно рассчитывается и проверяется для условия (может быть способ оптимизировать это с правильным индексом, но обычно Индекс здесь не поможет). Он также обычно возвращает намного больше результатов, что увеличивает время выполнения.

1 голос
/ 28 июля 2010

(вспоминая вопрос )

Вы пытаетесь подсчитать строки в Table1, для которых нет соответствующей записи в Table2?

Если это так, вы можете использовать это

SELECT COUNT(*) FROM Table1 TB1
WHERE NOT EXISTS
     (SELECT * FROM Table2 TB2 
      WHERE TB1.Field1 = TB2.Field2 )

или это например

SELECT COUNT(*)
FROM
(
SELECT Field1 FROM Table1 
MINUS
SELECT Field2 FROM Table2
) T
1 голос
/ 28 июля 2010

Вероятно, второй запрос обрабатывает путь больше строк, чем первый.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...