У меня следующий запрос SQL, который я перевел на HQL:
SELECT f.date,
f.name,
SUM(f.seats)
FROM Foo f
WHERE EXISTS ( SELECT 1
FROM Foo fh
WHERE f.start + f.end IN ( SELECT fl.start + fl.end
FROM Foo fl
WHERE fl.date BETWEEN dateadd(yy,-1,fh.date)
AND fh.date
AND fl.name = '<name>')
AND f.date = fh.date
AND fh.date >= '2016-01-01'
AND fh.name = '<name>' )
AND f.date >= '2016-01-01'
GROUP BY f.date,
f.name
ORDER BY f.date ASC,
SUM(f.seats) DESC
В моем приложении этот запрос вызывает ошибку в заголовке:
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Could not allocate a new page for database 'TEMPDB' because of insufficient disk space in filegroup 'DEFAULT'. Create the necessary space by dropping objects in the filegroup, adding additional files to the filegroup, or setting autogrowth on for existing files in the filegroup.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet$FetchBuffer.nextRow(SQLServerResultSet.java:4853)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet.fetchBufferNext(SQLServerResultSet.java:1781)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet.next(SQLServerResultSet.java:1034)
at org.apache.commons.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:191)
at org.apache.commons.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:191)
at org.hibernate.loader.Loader.processResultSet(Loader.java:986)
at org.hibernate.loader.Loader.doQuery(Loader.java:948)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:340)
at org.hibernate.loader.Loader.doList(Loader.java:2689)
Это, очевидно, вызванополная неэффективность запроса, а также количество выполнений и количество строк, с которыми он работает.
Позволяет объяснить, что делает запрос.Следующий пример:
У меня есть данные о драйверах Uber.Каждый ряд представляет собой один диск водителя с датой (месяцем), именем водителя, местами, которыми располагал водитель, местоположением начала и конца.
E.g.:
Date Name Seats Start End
-------------------------------------------
7/1/2019 John 45 A B
Данные суммируются за месяц.Таким образом, John
имел 9 дисков между A
и B
, и каждый раз у него было 5 свободных мест.Конечно, есть и другие люди, которые едут по тому же маршруту и поэтому выставляют себя на соревнование до John
.
Date Name Seats Start End
-------------------------------------------
7/1/2019 John 45 A B
7/1/2019 Doe 25 A A
7/1/2019 Alice 35 A C
7/1/2019 John 30 A A
7/1/2019 Doe 25 A C
7/1/2019 Alice 10 A B
7/1/2019 Doe 5 A B
7/1/2019 Alice 15 A A
Таким образом, для 7/1/2019
John
s «сеть» (все маршруты) проводила это соревнование:
Date Name Seats Route
---------------------------------
7/1/2019 John 30 A-A
7/1/2019 Doe 25 A-A
7/1/2019 Alice 15 A-A
7/1/2019 John 45 A-B
7/1/2019 Doe 5 A-B
7/1/2019 Alice 10 A-B
Как видно, в этом результате маршрут A-C
нет в списке, потому что John
его вообще не водил.Если мы расширим пример данных на новый месяц 8/1/2019
:
Date Name Seats Start End
-------------------------------------------
8/1/2019 John 65 A C
8/1/2019 Doe 25 A A
8/1/2019 Alice 35 A A
8/1/2019 Doe 25 A B
8/1/2019 Alice 10 A B
8/1/2019 Doe 5 A C
8/1/2019 Alice 15 A C
, мы увидим, что John
только увеличил A-C
в этом месяце.Поскольку network
должен быть построен за период в 1 год с прошлого (с 1 августа по 8 августа 2009 года), сеть John
теперь включает все три маршрута (A-A
, A-B
,A-C
), но только для расчета участников по состоянию на 8/1/2019
.Для 7/1/2019
, John
s сеть остается A-A
, A-B
.Таким образом, результат для 8/1/2019
таков:
Date Name Seats Route
---------------------------------
8/1/2019 John 0 A-A
8/1/2019 Doe 25 A-A
8/1/2019 Alice 35 A-A
8/1/2019 John 0 A-B
8/1/2019 Doe 25 A-B
8/1/2019 Alice 10 A-B
8/1/2019 John 65 A-C
8/1/2019 Doe 5 A-C
8/1/2019 Alice 10 A-C
John
только проехал A-C
, что является причиной, по которой ему подсчитано 0 мест для других маршрутов.
Поскольку результаты суммируют места и игнорируют маршрут, фактический результат запроса выглядит следующим образом:
7/1/2019 John 75 <-- 30+45
7/1/2019 Doe 30 <-- 25+5
7/1/2019 Alice 25 <-- 10+15
8/1/2019 John 65 <-- 65+0+0
8/1/2019 Doe 55 <-- 25+25+5
8/1/2019 Alice 55 <-- 35+10+10
В этом результате мы имеем в качестве маршрутов только 7/1/2019
* A-A
и A-B
для John
конкурентов, так как данных до этой даты нет.Для 8/1/2019
John
s сеть A-A
, A-B
и A-C
, хотя он проехал только A-C
в 8/1/2019
(A-A
и A-B
были в 7/1/2019
).
Надеюсь, предоставленные мной данные понятны.Если вам нужно больше разъяснений, просто спросите, и я постараюсь объяснить еще больше.
Как мне изменить свой запрос, чтобы значительно повысить производительность?
Я до сих пор не использовал JOIN
s, потому что мне пришлось присоединиться к подзапросу, а это не разрешено в HQL.
Если вам нужна дополнительная информация / разъяснения,не стесняйтесь спрашивать!
РЕДАКТИРОВАТЬ:
Я знаю, что я мог бы также опубликовать на codereview.stackexchange.com , но я выбрал противэто, потому что сам запрос работает, если только выполняется для 1 имени и не работает только для более.Я понимаю, что codereview.stackexchange.com
состоит в том, что должны быть только вопросы по улучшению производительности