2017-08-22 38 views
0

我正在使用基于表1和表2的两个表开发SQL查询。RDBMS是SQL Server。这两个表都有一个共同的ID列,根据该列构建连接。两列中都有一个日期时间列。优化对庞大数据库的选择查询

目标:我想检索表2中的所有行,其中Table2.datetime在1分钟范围内Table1.datetime

注意:我没有数据库的写入权限,所以索引不是我的选择。

我得到了正确的查询。它工作正常;然而,数据库是巨大的。如果我想从过去15天内检索数据,则需要永久。

有没有更好的方法来做到这一点?

下面是该查询

SELECT 
    A.Column1, A.Column2, 
    A.Column3, A.Column4, 
    A.Column5, A.Column6, 
    A.Column7, A.Column8, 
    A.Column9, A.Column10, A.Column11, 
    B.Column1, B.Column2, 
    B.Column3, B.Column4, B.Column5 
FROM 
    TABLE1 A, TABLE2 B 
WHERE 
    A.CommonColumn = B.CommonColumn 
    AND B.DateTime BETWEEN DATEADD(minute, -1, A.DateTime) 
         AND DATEADD(minute, 1, A.DateTime) 
    AND A.DateTime BETWEEN GETDATE() - 15 AND GETDATE() 
+12

[停止使用旧式连接(http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using-old-style-joins.aspx) – scsimon

+0

你也许可以预先计算'getdate() - 15'并将其作为常量插入。否则,恐怕你没有权限优化这种情况。 – LSerni

+2

寻求性能帮助的问题应包括DDL,DML所涉及的表格以及测试数据。如果您的测试数据很大,请尝试脚本化表格的模式和统计信息('右键单击数据库 - >生成脚本 - >选择特定数据库对象 - >在下一个屏幕选择高级并选择脚本统计)'并粘贴它的问题。有了这个信息任何一个repro面临同样的问题。否则它变得很难回答你的问题.Pasting服务器版本也有助于 – TheGameiswar

回答

0

尽量先筛选数据应用分钟的条件 还定义变量起始日期和结束日期,并在查询中使用他们像下面前减少的记录数。 (希望它能帮助,或给你一个想法) (恐怕对CTE的表现,但让我们尝试)

Declare @startDate Datetime =GetDate()-15; 
Declare @endDate Datetime=GetDate(); 

;with filteredDataA as (
SELECT A.CommonColumn,A.DateTime, 
    A.Column1, A.Column2, 
    A.Column3, A.Column4, 
    A.Column5, A.Column6, 
    A.Column7, A.Column8, 
    A.Column9, A.Column10, A.Column11 
FROM 
    TABLE1 A 
where A.DateTime BETWEEN @startDate AND @endDate 
), 
filteredDataB as (
Select B.CommonColumn,B.DateTime, 
B.Column1, B.Column2, 
B.Column3, B.Column4, B.Column5 
From Table2 B 
where B.DateTime BETWEEN @startDate AND @endDate 
) 

Select A.Column1, A.Column2, 
    A.Column3, A.Column4, 
    A.Column5, A.Column6, 
    A.Column7, A.Column8, 
    A.Column9, A.Column10, A.Column11, 
    B.Column1, B.Column2, 
    B.Column3, B.Column4, B.Column5 

    from filteredDataA A left join filteredDataB B on A.commonColumn=B.CommonColumn 
    and B.DateTime BETWEEN DATEADD(minute, -1, A.DateTime) 
         AND DATEADD(minute, 1, A.DateTime) 
+1

与流行的观点相反,使用CTE不会导致优化器按照CTE定义的“阶段”拆分查询。查询将被折回到主查询中,就好像你已经用文本替换它们作为子查询,然后整个过程被优化。这不会比原始查询更“先过滤数据”(或者不会,这取决于优化器认为哪种效果最好)。这在大多数情况下是幸运的,否则像这样的查询可能不会使用原始表上的索引。 –

0

尝试改变第二句话

WHERE 
A.CommonColumn = B.CommonColumn 
--AND B.DateTime BETWEEN DATEADD(minute, -1, A.DateTime) 
--     AND DATEADD(minute, 1, A.DateTime) 
AND ABS(DateDiff(mi, A.DateTime, B.DateTime)) <= 1 
AND A.DateTime BETWEEN GETDATE() - 15 AND GETDATE()