如何优化这个简单但缓慢的查询?

时间:2016-05-20 22:49:35

标签: sql sql-server optimization

我有一张旅行者表,其中包含大约200,000条记录,其中包含用户编号(pk),国家/地区和出发时间(日期时间)。我的目标是计算每个旅行者在同一个国家/地区的出发时间在一小时内离开的旅客人数。

所以我的输入看起来像

aMethod()

我的目标是获得

| Travel_no | Date_time              | Country|
|-----------+------------------------|--------|
|         1 |         20160401150200 |      1 |
|         2 |         20160401160000 |      2 |
|         3 |         20160401010501 |      3 |
|         4 |         20160401090700 |      2 |
|         5 |         20160401155800 |      1 |

现在我正在使用这个查询,它将永远运行它......

| Travel_no | Date_time              | Country| country_within_hr_cnt|
|-----------+------------------------|--------|----------------------|
|         1 |         20160401150200 |      1 |                    2 |
|         2 |         20160401160000 |      2 |                    1 |
|         3 |         20160401010501 |      3 |                    1 |
|         4 |         20160401090700 |      2 |                    1 |
|         5 |         20160401155800 |      1 |                    2 |

你们知道是否有办法让这个跑得更快? Date_time上的索引是否运作良好?

2 个答案:

答案 0 :(得分:2)

这样想:对于a的分组结果中的每一行,它必须扫描整个b表,因为要评估条件,它必须计算强制转换。当你安排它时它会很快,因此b在你条件中访问的列上被索引,并且你的条件引用了未经加工的b列 - 即列值就像它们存储在b中一样。 您希望查询看起来像这样:

Select 
Travel_no
,Date_time
,Country
,(Select Count(Travel_no) from #temp1 b
  where 
  b.Date_time >= a.Date_time - 10000 
  and b.Date_time <= a.Date_time + 10000 
  and a.Country = b.Country
  ) 'country_within_hr_cnt'
FROM #temp1 a
GROUP BY 
Travel_no , Date_time, Country

但即便如此也可以

Select 
Travel_no
,Date_time
,Country
,(Select Count(Travel_no) from #temp1 b
  where 
  b.Date_time >= CAST(varchar(20),CAST(a.Date_time AS BIGINT) - 10000)
  and b.Date_time <= CAST(varchar(20),CAST(a.Date_time AS BIGINT) + 10000) 
  and a.Country = b.Country
  ) 'country_within_hr_cnt'
FROM #temp1 a
GROUP BY 
Travel_no , Date_time, Country

这假设您已在Country和Date_time上编入索引。

答案 1 :(得分:1)

我想在这里讨论两个方面:

避免SELECT中的相关子查询:

尽可能不惜一切代价避免SELECT语句中的相关子查询。 原因是逻辑上SQL服务器必须为外部SELECT语句返回的每一行运行子查询,因此如果外部SELECT返回1000行,则子查询在逻辑上将执行1000次。在实践中,SQL Server通常能够对其进行优化,并将子查询从SELECT移动到FROM子句,但如果不发生这种情况,则性能会降低。

表连接中的函数:

正如之前的评论中的海报所说,避免在连接表时使用函数,因为这会导致SQL Server不在函数内的列上使用索引(如果有的话)。

我会按如下方式重新编写您的查询:

$scope.redirectSearchCardUrl = function(setIdNum, name) {
        var url = "/card/"+setIdNum+ "/"+name;
        $scope.hideVar = true;
        $location.path(url);    
    }