Самый быстрый способ проверить наличие записей в таблице базы данных? - PullRequest
10 голосов
/ 25 января 2010

У меня есть огромный стол для работы. Я хочу проверить, есть ли какие-либо записи, чей parent_id равен моему передаваемому значению. в настоящее время я реализую это с помощью «select count (*) from mytable where parent_id =: id»; если результат> 0, значит, они существуют.

Поскольку это очень большая таблица, и мне все равно, сколько именно существует записей, я просто хочу знать, существует ли она, поэтому я считаю, что count (*) немного неэффективен.

Как мне выполнить это требование самым быстрым способом? Я использую Oracle 10.

#

Согласно Hibernate Советы и хитрости https://www.hibernate.org/118.html#A2

Он предлагает написать так:

Integer count = (Integer) session.createQuery ("выберите количество (*) из ...."). UniqueResult ();

Я не знаю, что здесь за магия uniqueResult ()? почему так быстро?

Сравните с "select 1 from mytable, где parent_id =passId и rowrum <2", что более эффективно? </p>

Ответы [ 6 ]

11 голосов
/ 25 января 2010

Запрос EXISTS - тот, на который нужно пойти, если вас не интересует количество записей:

select 'Y' from dual where exists (select 1 from mytable where parent_id = :id)

Это вернет 'Y', если запись существует, и ничего иначе.

[С точки зрения вашего вопроса об "uniqueResult" в Hibernate - все, что он делает, это возвращает один объект, когда требуется вернуть только один объект - вместо набора, содержащего 1 объект. Если возвращается несколько результатов, метод вызывает исключение.]

5 голосов
/ 26 января 2010

select count (*) должен быть очень быстрым, если у вас есть индекс, а если нет, то разрешение базы данных прервать работу после первого совпадения не очень поможет.

Но так как вы спросили:

boolean exists = session.createQuery("select parent_id from Entity where parent_id=?")
                        .setParameter(...)
                        .setMaxResults(1)
                        .uniqueResult() 
                 != null;

(Ожидаются некоторые синтаксические ошибки, поскольку у меня нет гибернации для тестирования на этом компьютере)

Для Oracle maxResults переводится в rownum hibernate.

Что касается того, что делает uniqueResult (), прочитайте его JavaDoc! Использование uniqueResult вместо list () не влияет на производительность; если я правильно помню, реализация uniqueResult делегатов для list ().

4 голосов
/ 26 января 2010

Нет реальной разницы между:

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)
2 голосов
/ 25 января 2010

Прежде всего, вам нужен индекс для mytable.parent_id.

Это должно сделать ваш запрос достаточно быстрым, даже для больших таблиц (если в нем также много строк с одинаковым parent_id).

Если нет, вы можете написать

select 1 from mytable where parent_id = :id and rownum < 2

, который вернул бы одну строку, содержащую 1, или никакой строки вообще. Не нужно считать строки, просто найдите и выйдите. Но это специфичный для Oracle SQL (из-за rownum), и вам лучше этого не делать.

0 голосов
/ 31 марта 2015

Этот запрос вернет 1, если какая-либо запись существует, и 0 в противном случае:

SELECT COUNT(1) FROM (SELECT 1 FROM mytable WHERE ROWNUM < 2);

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

0 голосов
/ 25 января 2010

Для DB2 есть что-то вроде select * from mytable where parent_id = ? fetch first 1 row only. Я предполагаю, что нечто подобное существует для оракула. ​​

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