|
|
|
Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
|
|||
|---|---|---|---|
|
#18+
В общем есть один тормозящий уже слегка запрос. Сейчас есть время и хочется разобраться самостоятельно. Поэтому чужое мнение будет интересно, особенно тех кто уже имеет богатый опыт использования 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. Код: 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. Вот что схема которую создает 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2015, 12:35 |
|
||
|
Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
|
|||
|---|---|---|---|
|
#18+
Какой глубинный смысл в вычислении агрегатов через Hibernate? При том что на сам агрегат у вас никакой сущности нет. Заведите SQL запрос и не мучайтесь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2015, 12:42 |
|
||
|
Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
|
|||
|---|---|---|---|
|
#18+
Просто я работал с Hibernate, а сейчас больше работаю с БД в чистом ввиде. Раньше БД были маленькие и проблем производительности вообще не возникало, поэтому не парился вообще, все работало с hibernate из коробки без колдовства. А теперь БД стали больше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2015, 12:51 |
|
||
|
Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
|
|||
|---|---|---|---|
|
#18+
AFAIK, для наследования нет никакого хинта, так как ленивость наследование реализовать не так уж и просто. При этом совершенно не понятно зачем цепляться за HQL, в запросе select surname, count(*). Переписать на SQL должно быть очень просто, если нет других джоинов. Альтернативой может быть разве что замена маппинга. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2015, 13:12 |
|
||
|
Правильно сформировать(соптимизировать) hql запрос (EntityInheritance в Hibernate)
|
|||
|---|---|---|---|
|
#18+
Так уже было реализовано. Логи БД анализировал и нашел этот пример где этот inner join не хило портит производительность вот и стал думал. Из-за этого не один запрос без inner join можно на 2 порядка ускорить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2015, 13:30 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=38909749&tid=2125675]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
148ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
40ms |
get tp. blocked users: |
2ms |
| others: | 199ms |
| total: | 428ms |

| 0 / 0 |
