HQL查询导致磁盘不足space异常
HQL query causing insufficient disk space exception
我有以下 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)
这显然是由于查询效率低下及其执行次数和处理的行数造成的。
让我们解释查询的作用。以下示例:
我有优步 driver 的数据。每行是 driver 的一个驱动器,带有日期(月)、driver 名称、driver 可用的座位、开始位置和结束位置。
E. g.:
Date Name Seats Start End
-------------------------------------------
7/1/2019 John 45 A B
数据按月汇总。所以 John
在 A
和 B
之间有 9 次驾驶,每次他都有 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 "network" (所有路线) 有这个比赛:
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
应该建立在过去一年的时间跨度(8/1/2018 到 8/1/2019),John
s 网络现在是所有三个路线(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
的网络是 A-A
、A-B
和 A-C
,即使他只在 8/1/2019
开车 A-C
(A-A
和 A-B
在 7/1/2019
中)。
我希望我提供的数据是可以理解的。如果您需要更多说明,请直接提问,我会尽力解释更多。
我需要如何更改查询才能大大提高性能?
到目前为止我还没有使用 JOIN
s,因为我必须加入子查询,而这在 HQL 中是不允许的。
如果您需要更多info/clarification,请随时询问!
编辑:
我知道我也可以在 codereview.stackexchange.com 上发帖,但我选择了反对,因为查询本身是有效的,如果只对 1 个名称执行并且只对更多名称执行失败。我对codereview.stackexchange.com
的理解是,应该只有性能提升问题
我在发布问题后不久想到了这个查询:
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
子句。我不太确定这样做是否正确,或者这可能导致什么错误,但它至少解决了手头的错误(磁盘不足 space 异常)。
如果您对我的查询有其他想法或评论,请随时分享!
我有以下 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)
这显然是由于查询效率低下及其执行次数和处理的行数造成的。
让我们解释查询的作用。以下示例:
我有优步 driver 的数据。每行是 driver 的一个驱动器,带有日期(月)、driver 名称、driver 可用的座位、开始位置和结束位置。
E. g.:
Date Name Seats Start End
-------------------------------------------
7/1/2019 John 45 A B
数据按月汇总。所以 John
在 A
和 B
之间有 9 次驾驶,每次他都有 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 "network" (所有路线) 有这个比赛:
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
应该建立在过去一年的时间跨度(8/1/2018 到 8/1/2019),John
s 网络现在是所有三个路线(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
的网络是 A-A
、A-B
和 A-C
,即使他只在 8/1/2019
开车 A-C
(A-A
和 A-B
在 7/1/2019
中)。
我希望我提供的数据是可以理解的。如果您需要更多说明,请直接提问,我会尽力解释更多。
我需要如何更改查询才能大大提高性能?
到目前为止我还没有使用 JOIN
s,因为我必须加入子查询,而这在 HQL 中是不允许的。
如果您需要更多info/clarification,请随时询问!
编辑:
我知道我也可以在 codereview.stackexchange.com 上发帖,但我选择了反对,因为查询本身是有效的,如果只对 1 个名称执行并且只对更多名称执行失败。我对codereview.stackexchange.com
的理解是,应该只有性能提升问题
我在发布问题后不久想到了这个查询:
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
子句。我不太确定这样做是否正确,或者这可能导致什么错误,但它至少解决了手头的错误(磁盘不足 space 异常)。
如果您对我的查询有其他想法或评论,请随时分享!