HQL-запрос, вызывающий нехватку места на диске - PullRequest
0 голосов
/ 22 февраля 2019

У меня следующий запрос 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 состоит в том, что должны быть только вопросы по улучшению производительности

1 Ответ

0 голосов
/ 25 февраля 2019

Я пришел к этому запросу вскоре после публикации вопроса:

SELECT f.date,
    f.name,
    SUM(f.seats) 
FROM Foo f 
WHERE f.start + f.end IN (  SELECT fh.start + fh.end 
                            FROM Foo fh 
                            WHERE fh.date BETWEEN DATEADD(yy, -1, f.date) 
                                AND f.date 
                                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

Как видите, я почти полностью удалил предложение WHERE EXISTS.Я не совсем уверен, что это было правильно, или какие ошибки это могло вызвать, но это, по крайней мере, помогло устранить ошибку (нехватка места на диске).

Если у вас есть другая идея или замечанияна мой запрос, не стесняйтесь поделиться ими!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...