powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
5 сообщений из 5, страница 1 из 1
Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
    #38909675
lleming
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем есть один тормозящий уже слегка запрос. Сейчас есть время и хочется разобраться самостоятельно. Поэтому чужое мнение будет интересно, особенно тех кто уже имеет богатый опыт использования hibernate.

Доступа к исходинкам у меня нет, но удалось написать entity которые формируют аналогичный запрос и образуют соотвуствующую схему в БД. Конструкторы я пропустил.
(Postgres)

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
package org.myproject.entities;
import *;

@Entity
@Table(name = "generic_object")
@Inheritance(strategy = InheritanceType.JOINED)
public class GenericObject {

	@Id
	@SequenceGenerator(name = "GENERIC_OBJECT_ID", sequenceName = "generic_object_id_seq")
	@GeneratedValue(generator = "GENERIC_OBJECT_ID")
	private Long id;

	@ManyToOne(optional = false)
	private GenericObjectType type;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public GenericObjectType getType() {
		return type;
	}

	public void setType(GenericObjectType type) {
		this.type = type;
	}

}



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
package org.myproject.entities;

@Entity
@Table(name = "individual")
public class Individual extends GenericObject {

	@Column(name = "id", insertable = false, updatable = false)
	private Long id;

	private String surname;
	@Column(name = "patr_name")
	private String patrName;
	private String name;
	@Column(name = "birth_dt")
	private Date birthDt;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getSurname() {
		return surname;
	}

	public void setSurname(String surname) {
		this.surname = surname;
	}

	public String getPatrName() {
		return patrName;
	}

	public void setPatrName(String patrName) {
		this.patrName = patrName;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Date getBirthDt() {
		return birthDt;
	}

	public void setBirthDt(Date birthDt) {
		this.birthDt = birthDt;
	}

	@Override
	public String toString() {
		return "Individual [id=" + id + ", surname=" + surname
				+ ", patrName=" + patrName + ", name=" + name + ", birthDt="
				+ birthDt + "]";
	}

}


Вот что схема которую создает hibernate
create table individual (birth_dt timestamp, id int8, name varchar(255), patr_name varchar(255), surname varchar(255), primary key (id))
create table generic_object (id int8 not null, type_id int8 not null, primary key (id))
create table generic_object_type (id int8 not null, name varchar(255), primary key (id))
alter table individual add constraint FK_64g5v3sfkusgss8djc60kqqxf foreign key (id) references generic_object
alter table generic_object add constraint FK_meom0nwdailrmpld8c93b0axs foreign key (type_id) references generic_object_type

GenericObjectType я пропустил так он особой роли не играет.

Мне интересен тот момент, что hibernate соображает что раз объект GenericObject предок Individual и они клеятся через id, то создается foreign key гарантирующий, что у каждого Individual обязательно был GenericObject, или говоря языком БД каждая запись в таблице individual имеет соотвествующую запись с аналогичным id в таблице generic_object .

Теперь все запросы к Individual hibernate будет формировать через inner join. В этом в принципе нет ничего страшного, так как чтобы создать объект Individual обязательно надо сначала создать объект GenericObject, поскольку имеются наследуемые свойства.

Рассмотрим запрос hql:
"select i.surname, i.name, i.partName from Individual i where i = 25"
Hibernate сгенерирует:
"select _individual0.surname, _individual0.name, _individual0.patr_name from individual _individual0 inner join generic_object on _object0_ on _individual0.id = _object.id where _individual0.id = 25"

Здесь присутвует inner join несмотря на то что данные из таблицы generic_object не извлекаются.
Это не проблема так выборка ограниченая и с помощью индексов inner join формируется очень эффективно.

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

Пример (это общий пример на самом деле выборка ограничивается)
"select i.surname, count(*) from Individual group by i.surname order by 2 desc"
Из за того что нужно извлечь множество записей из individual, то БД генерирует план запроса из таблицы individual SeqScan затем все это множество через hash join джойнится с generic_object (которая еще больше).
Вот этот отнюдь не необходимый join и занимает много времени так как таблицы большие очень стали. По сути никакие данные из таблицы generic_object не подтягиваются поэтому и необходимости в inner join нет(И есть даже внешний ключ гарантирующий целостность)


Вот мои идеи.
1. Так как совсем не обязательно, что схема БД генерируется hibernate, то даже несмотря на то что сам Hibernate при генерации создает внешний ключ соединяющий таблицы, не факт что потом его(внешний ключ) не удалят/отключат ручками. Возможен вариант когда Hibernate натянут поверх уже работающей БД, и в ней этого внешнего ключа не будет.
2. Возможно имеется анотация, которая укажет Hibernate что все таки есть внешний ключ и совсем необязательно делать inner join. (Соотвественно если такая аннотация есть и проставлена в entity, то при инициализации hibernate по идее должен воспротивиться работе при отсутствующем ключе)
3. Возможно есть какой либо hint который скажет Hibernate забей на Inner join, он необязателен.

Думаю разработчики пошли по пути "не надо переусложнять систему" и так как узнать что foreing key есть можно только запросом к БД при инициализации, либо созданием ключа при инициализации с помощью "if not exist ". Поэтому анотация вряд ли существует.

А вот с хинтами не уверен.
Ну естесно как самый простой вариант воспользоваться обыкновенным наитивным sql.
...
Рейтинг: 0 / 0
Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
    #38909693
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Какой глубинный смысл в вычислении агрегатов через Hibernate? При том что на сам агрегат у вас никакой сущности нет. Заведите SQL запрос и не мучайтесь.
...
Рейтинг: 0 / 0
Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
    #38909716
lleming
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Просто я работал с Hibernate, а сейчас больше работаю с БД в чистом ввиде. Раньше БД были маленькие и проблем производительности вообще не возникало, поэтому не парился вообще, все работало с hibernate из коробки без колдовства.
А теперь БД стали больше.
...
Рейтинг: 0 / 0
Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
    #38909749
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AFAIK, для наследования нет никакого хинта, так как ленивость наследование реализовать не так уж и просто.
При этом совершенно не понятно зачем цепляться за HQL, в запросе select surname, count(*). Переписать на SQL должно быть очень просто, если нет других джоинов.
Альтернативой может быть разве что замена маппинга.
...
Рейтинг: 0 / 0
Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
    #38909784
lleming
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так уже было реализовано.
Логи БД анализировал и нашел этот пример где этот inner join не хило портит производительность вот и стал думал.

Из-за этого не один запрос без inner join можно на 2 порядка ускорить.
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]