У меня есть огромная таблица для работы. Я хочу проверить, есть ли какие-то записи, parent_id которых равно моему передаваемому значению.
в настоящее время я реализую это, используя "select count (*) из mytable, где parent_id =: id"; если результат > 0, означает, что они существуют.
Потому что это очень огромная таблица, и мне все равно, сколько именно записей существует, я просто хочу знать, существует ли она, поэтому я считаю, что count (*) немного неэффективен.
Как реализовать это требование самым быстрым способом? Я использую Oracle 10.
#
В соответствии с hibernate Советы и подсказки https://www.hibernate.org/118.html#A2
Предлагается написать вот так:
Целое число count = (целое число) session.createQuery( "select count (*) from...." ). uniqueResult();
Я не знаю, что это за волшебство uniqueResult() здесь? почему он делает это быстро?
Сравнить с "выберите 1 из mytable, где parent_id = passId и rowrum < 2", что более эффективно?
Ответ 1
Запрос EXISTS - это тот, который нужно выполнить, если вас не интересует количество записей:
select 'Y' from dual where exists (select 1 from mytable where parent_id = :id)
Это вернет "Y", если запись существует и ничего не происходит.
[С точки зрения вашего вопроса в Hibernate "uniqueResult" - все это возвращает один объект, когда возвращается только один объект - вместо набора, содержащего 1 объект. Если возвращено несколько результатов, метод выдает исключение.]
Ответ 2
select count (*) должен быть молниено быстрым, если у вас есть индекс, а если нет, то разрешить остановке базы данных после первого совпадения не поможет.
Но так как вы спросили:
boolean exists = session.createQuery("select parent_id from Entity where parent_id=?")
.setParameter(...)
.setMaxResults(1)
.uniqueResult()
!= null;
(Некоторые ожидаемые синтаксические ошибки, так как у меня нет спящего режима для тестирования на этом компьютере)
Для Oracle maxResults транслируется в rownum с помощью спящего режима.
Что касается того, что делает uniqueResult(), прочитайте его JavaDoc! Использование uniqueResult вместо списка() не влияет на производительность; если я правильно помню, реализация делегатов uniqueResult для list().
Ответ 3
Нет реальной разницы между:
select 'y'
from dual
where exists (select 1
from child_table
where parent_key = :somevalue)
и
select 'y'
from mytable
where parent_key = :somevalue
and rownum = 1;
... по крайней мере, в Oracle10gR2 и выше. Oracle достаточно умна в этом выпуске, чтобы выполнить операцию FAST DUAL, где она обнуляет любую реальную активность против нее. Второй запрос будет проще переносить, если это когда-либо будет рассмотрено.
Реальным отличием производительности является то, проиндексирован ли столбец parent_key. Если это не так, вы должны запустить что-то вроде:
select 'y'
from dual
where exists (select 1
from parent_able
where parent_key = :somevalue)
Ответ 4
Прежде всего, вам нужен индекс на mytable.parent_id.
Это должно сделать ваш запрос достаточно быстрым даже для больших таблиц (если не существует также много строк с одним и тем же parent_id).
Если нет, вы можете написать
select 1 from mytable where parent_id = :id and rownum < 2
который возвратит одну строку, содержащую 1, или вообще не строку. Нет необходимости подсчитывать строки, просто найти их и затем выйти. Но это Oracle-специфический SQL (из-за rownum), и вы не должны этого делать.
Ответ 5
Для DB2 есть что-то вроде select * from mytable where parent_id = ? fetch first 1 row only
. Я предполагаю, что существует нечто подобное для оракула.
Ответ 6
Этот запрос вернет 1, если какая-либо запись существует, а 0 в противном случае:
SELECT COUNT(1) FROM (SELECT 1 FROM mytable WHERE ROWNUM < 2);
Это может помочь, когда вам нужно проверить статистику данных таблицы, независимо от размера таблицы и любой проблемы с производительностью.