Лучший способ написать именованный запрос SQL, который возвращает, если строка существует? - PullRequest
1 голос
/ 13 февраля 2010

Итак, у меня есть SQL-запрос,

<named-query name="NQ::job_exists">
<query>
select 0 from dual where exists (select * from job_queue);
</query>
</named-query>

Который я планирую использовать так:

Query q = em.createNamedQuery("NQ::job_exists");
        List<Integer> results = q.getResultList();
        boolean exists = !results.isEmpty();
        return exists;

Однако я не очень силен в SQL / JPA, и мне было интересно, есть ли лучший способ сделать это (или способы улучшить его). Должен ли я, например, написать (выбрать jq.id из job_queue jq) вместо использования звездочки ??

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

РЕДАКТИРОВАТЬ: провел некоторое тестирование производительности, и, хотя различия были почти незначительными, я наконец решил пойти с:

select distinct null
    from dual 
       where exists (
               select null from job_queue
       );

Ответы [ 3 ]

5 голосов
/ 13 февраля 2010

ЕСЛИ вы используете EXISTS Oracle, я рекомендую использовать null:

select null 
  from dual where exists (select null from job_queue);

Следующим будет тот, который дешевле в Oracle:

select null
  from job_queue
 where rownum = 1;

Обновление: Чтобы включить случай, когда в таблице нет строк, можно выполнить следующий запрос:

select count(*)
  from (select null
          from job_queue
          where rownum = 1);

С этим запросом у вас есть оптимальный план и только два возможных результата: 1, если есть строки, и 0, если нет строк.

3 голосов
/ 13 февраля 2010

Если вы сделаете «существует», он перестанет искать, как только найдет совпадение. Это может помешать выполнению полного сканирования таблицы. То же самое с TOP 1, если у вас нет ORDER BY. Если вы делаете TOP 1 ID и ID в индексе, он может использовать индекс и даже не переходить к таблице вообще. Остановка полного сканирования таблицы - это самая большая экономия производительности.

Другая небольшая экономия заключается в том, что если вместо «SELECT *» или «SELECT COUNT (*)» вместо «SELECT *» или «SELECT COUNT (*)» выполнить «SELECT 1» или «SELECT COUNT (*)», это сэкономит работу по получению структуры таблицы.

Так что я бы пошел с:

SELECT TOP 1 1 AS Found
FROM job_queue

Тогда:
return! results.isEmpty ();

Это наименьший объем работы, который я могу придумать.

Для Oracle это будет:

SELECT 1 
FROM job_queue
WHERE rownum<2;

Или:

Set Rowcount 1
SELECT 1 
FROM job_queue
1 голос
/ 13 февраля 2010

Почему бы просто не сделать:

select count(*) as JobCount from job_queue

Если JobCount = 0, тогда ваш ответ!

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