我有以下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)
这显然是由于查询的效率低下,其执行的次数以及处理的行数引起的。
让我们解释一下查询的作用。以下示例:
我有关于超级驱动程序的数据。每行是一个驱动器驱动器,其中包含日期(月),驱动器名称,驱动器可用的座位,起始位置和结束位置。
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
的“网络”(所有路线)进行了以下竞争:
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
应该在过去的一年(从2018年8月1日到2019年8月1日)之间建立,因此John
的网络现在是所有三个路由({{1} },A-A
,A-B
),但仅用于计算A-C
起的竞争对手。对于8/1/2019
,7/1/2019
的网络保持John
,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
,这就是为什么他被计为其他路线0席的原因。
由于结果是席位总和而忽略了路线,因此查询的实际输出如下:
A-C
在此结果中,我们只有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
到A-C
({ {1}}和8/1/2019
在A-A
中)。
我希望我提供的数据是可以理解的。如果您需要更多说明,请询问,我将尝试进一步解释。
如何更改查询以大大提高性能?
到目前为止,我还没有使用过A-B
,因为我必须加入一个子查询,而HQL不允许这样做。
如果您需要更多信息/说明,请随时询问!
编辑:
我知道我也可以发布在codereview.stackexchange.com上,但是我反对这样做,因为如果只对1个名称执行查询,而对更多名称执行失败,则查询本身可以工作。我对7/1/2019
的理解是,应该只存在性能改进问题
答案 0 :(得分:0)
发布问题后不久,我想到了这个查询:
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
子句。我不确定这是正确的做法还是可能导致什么错误,但是至少可以解决手头的错误(磁盘空间不足)。
如果您对我的查询还有其他想法或意见,请随时与我们分享!