Когда я должен использовать примитивы вместо того, чтобы перенести объекты?

Вы можете использовать агрегированную функцию COUNT для удаления всех дублированных строк.

select PRINCIPAL, APELLIDO, NOMBRE,
count(*) over (partition by PRINCIPAL) dup_cnt
from tab

P A N    DUP_CNT
- - - ----------
a b c          2
a l m          2
b c d          1
c d e          1

COUNT подсчитывают строки для каждого уникального ключа, определенного в предложении PARTITION BY.

В последнем запросе выбираются только уникальные строки, то есть строки с DUP_CNT = 1

with dedup as (
select PRINCIPAL, APELLIDO, NOMBRE,
count(*) over (partition by PRINCIPAL) dup_cnt
from tab)
select PRINCIPAL, APELLIDO, NOMBRE
from dedup
where dup_cnt = 1

Примечание: используя ROW_NUMBER вместо COUNT, вы можете сделать дедупликация, т.е. вы позволяете одной из дублированных строк в результате и удаляете дубликаты.

Обратите внимание , что этот метод требует сортировки таблицы (WINDOW SORT), которая может быть тяжелой для больших таблиц. В этом случае метод, использующий NOT EXISTS, может дать лучшую производительность, так как он преобразуется и выполняется как антихеш-соединение - HASH JOIN RIGHT ANTI.

select principal, apellido, nombre 
from tab t
where not exists 
(select null
 from tab 
 where  principal = t.principal and rowid <> t.rowid
)

Необходимо соблюдать осторожность, если столбец дедупликации (principal) имеет значение NULL. В отличие от первого решения с COUNT not exusts оставляет все null в результате. Если это не требуется, необходимо добавить фильтр:

 and t.principal is not NULL

Если у вас есть индекс в столбце pricipal, оптимальный план выполнения выглядит следующим образом

--------------------------------------
| Id  | Operation             | Name | 
--------------------------------------
|   0 | SELECT STATEMENT      |      |    
|*  1 |  HASH JOIN RIGHT ANTI |      |     
|   2 |   INDEX FAST FULL SCAN| IDX  |  
|*  3 |   TABLE ACCESS FULL   | TAB  |  
--------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("PRINCIPAL"="T"."PRINCIPAL")
       filter(ROWID<>"T".ROWID)
   3 - filter("T"."PRINCIPAL" IS NOT NULL)

15
задан Community 23 May 2017 в 11:54
поделиться

5 ответов

Не забывайте, что, начиная с создания новой обертки для каждого возникновения упаковки является довольно дорогим, особенно рассматривая это обычно используемый в единственном объеме метода, Автоупаковывая использование пул общих оберток.

Это - на самом деле реализация шаблона разработки в наилегчайшем весе. Когда упаковка происходит для известного значения, вместо того, чтобы создать новый экземпляр обертки, предварительно созданный экземпляр выбирается от пула и возвращается.

Одно последствие: все еще не рекомендуется использовать автоупаковку для научных вычислений. Например, код d = * b + c использует Целочисленные классы для a, b, c и d, и сгенерированный код является d.valueOf (a.intValue () * b.intValue () + c.intValue ()). Все эти вызовы метода имеют свои собственные издержки, таким образом, обычно рекомендуется использовать автоупаковку при необходимости для хранения примитивов в наборах.

И даже затем, если у Вас есть огромный набор Целочисленного интервала обертывания, издержки могут подразумевать более длительное время выполнения, до 20 раз дольше, как сообщается в этой статье.


Jb добавляет этот важный комментарий:

Также Wrapper.valueOf (примитивный) пул использования оберток. Поэтому предпочтите Integer.valueOf (5) новому Целому числу (5)

23
ответ дан 1 December 2019 в 01:00
поделиться

Примитивы быстрее, когда они используются, поскольку объекты должны быть распакованы перед использованием; таким образом существует дополнительный шаг для VM для выполнения. Например, В порядке выполняют арифметику на Целом числе, это должно сначала быть преобразовано в интервал, прежде чем арифметика сможет быть выполнена.

Во многих бизнес-приложениях это, вероятно, редко имеет значение. Но если бы Вы писали что-то, очень numnber-уплотняя тяжелый как, скажем, графический процессор преобразования, то Вы, намного более вероятно, заботились бы.

10
ответ дан 1 December 2019 в 01:00
поделиться

Если Вы должны сохранить примитивы в наборах, Вы могли бы использовать примитивы свободного городского населения.

Я предпочитаю использовать примитивы для оберток, только помещаю, это абсолютно должно иметь обертки, классы объекта. Поддержка баз данных аннулирует, таким образом, объекты должны также.

Я когда-то работал над проектом, который использовал примитивы (и домашнее пиво ORM) в доступе к базе данных:

 class Foo{
    int xxx = -1;
 ...
 }

И затем Вы имели:

 void persist(Foo foo){
     ...
     statement.setInt(15,foo.getXXX()==-1?null:foo.getXXX());
     ...
}

Бог это было злым.

1
ответ дан 1 December 2019 в 01:00
поделиться

да, примитивы быстрее, чем объекты. Начиная с java 5 можно даже смешать примитивы и объекты, вручную не преобразовывая один в другого. Механизм автоупаковки заботится о просто этом.

это означает, что при помещении примитива в набор компилятор не будет жаловаться и преобразовывать примитив в объект неявно.

5
ответ дан 1 December 2019 в 01:00
поделиться

Я сказал бы, что Вы должны быть взволнованы по поводу использования примитивов по оберткам только, когда Вы представляете свое приложение и видите, что автоупаковка является производительностью или проблемой памяти. По моему опыту, память становится проблемой перед циклами ЦП при разговоре о примитивах по сравнению с обертыванием объектов.

1
ответ дан 1 December 2019 в 01:00
поделиться
Другие вопросы по тегам:

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