Запрос лучшей производительности для “выбора макс. в группе”?

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

Exception, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num. Перед созданием объекта вы получите NullPointerException. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

В этом случае вы не создаете объект obj, скорее предполагая, что он был создан до вызова метода doSomething. К сожалению, этот метод можно вызвать следующим образом:

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

14
задан mskfisher 8 June 2012 в 18:37
поделиться

7 ответов

Вот один путь, который с соответствующей индексацией не будет отвратительно медленным, и это не использует подвыбор:

SELECT comments.ID, comments.revision, comments.comment FROM comments 
LEFT OUTER JOIN comments AS maxcomments 
ON maxcomments.ID= comments.ID
AND maxcomments.revision > comments.revision
WHERE maxcomments.revision IS NULL

Адаптированный от запросов здесь: http://www.xaprb.com/blog/2007/03/14/how-to-find-the-max-row-per-group-in-sql-without-subqueries/

(От поиска Google: макс. группа sql)

11
ответ дан 1 December 2019 в 12:40
поделиться
  1. Удостоверяются, что Вам настраивали Ваши индексы соответственно. Индексируя на идентификаторе, пересмотр был бы хорош.

  2. Вот другое взятие на Вашем запросе. Не проверили его план выполнения, но если Вы настраиваете индекс хорошо, он должен помочь:

    SELECT c.* 
      FROM comments c
      INNER JOIN (
            SELECT id,max(revision) AS maxrev 
              FROM comments 
              GROUP BY id
      ) b
        ON c.id=b.id AND c.revision=b.maxrev
    

Editted для добавления:

  1. , Если Вы находитесь на SQL Server, Вы могли бы хотеть проверить Индексные представления также:
    http://www.microsoft.com/technet/prodtechnol/sql/2005/impprfiv.mspx

Editted снова для добавления информации:

Subquery:
25157 records
2 seconds
Execution plan includes an Index Seek (82%) base and a Segment (17%)

Left Outer Join:
25160 records
3 seconds
Execution plan includes two Index Scans @ 22% each with a Right Outer Merge at 45% and a Filter at 11%

я все еще пошел бы с запросом sub.

6
ответ дан 1 December 2019 в 12:40
поделиться

Аналитика была бы моей рекомендацией.

select id, max_revision, comment
from (select c.id, c.comment, c.revision, max(c.revision)over(partition by c.id) as max_revision
      from comments c)
where revision = max_revision;
1
ответ дан 1 December 2019 в 12:40
поделиться

Идея от левой стороны поля, но что относительно того, чтобы добавить дополнительное поле к таблице:

CurrentRevision bit not null

Затем при внесении изменения установите флаг на новом пересмотре и удалите его на всех предыдущих.

Ваш запрос затем просто стал бы:

select  Id,
        Comment
from    Comments
where   CurrentRevision = 1

Это было бы намного легче на базе данных и поэтому намного быстрее.

0
ответ дан 1 December 2019 в 12:40
поделиться

Протестированный с одной из наших таблиц, которая имеет почти 1 миллион общих количеств строк. Индексы существуют на обоих полях FIELD2 AND FIELD3. Запрос возвратил 83 953 строки через менее чем 3 секунды на нашем dev поле.

select
FIELD1, FIELD2, FIELD3
from
OURTABLE (nolock) T1
WHERE FIELD3 = 
(
SELECT MAX(FIELD3) FROM 
OURTABLE T2 (nolock)
WHERE T1.FIELD2=T2.FIELD2
)
ORDER BY FIELD2 DESC
4
ответ дан 1 December 2019 в 12:40
поделиться

Один довольно очевидный способ, чтобы сделать "последний x идентификатором" запросы типа является этим. Должно также быть довольно легко индексировать правильно.

SELECT id, revision, comment 
FROM comments
WHERE (id, revision) IN (
  SELECT id, MAX(revision)
  FROM comments
  -- WHERE clause comes here if needed
  GROUP BY id
)
0
ответ дан 1 December 2019 в 12:40
поделиться

Для больших таблиц я нахожу, что это решение может иметь лучшую производительность:

    SELECT c1.id, 
           c1.revision, 
           c1.comment 
      FROM comments c1 
INNER JOIN ( SELECT id, 
                max(revision) AS max_revision
               FROM comments 
           GROUP BY id ) c2
        ON c1.id = c2.id
       AND c1.revision = c2.max_revision
0
ответ дан 1 December 2019 в 12:40
поделиться
Другие вопросы по тегам:

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