SQL多行到列的性能非常慢

时间:2015-11-04 17:53:16

标签: sql sql-server pivot-table

我在使用特定的SQL行到列转换时遇到严重的性能问题。单个查询最多需要一分钟才能获得6小时的数据。为了清晰起见,我简化了下面的表格,但是每天有超过一百万的数据点,因此表格大小可能有所贡献。我对这样的复杂查询没有多少经验,所以我想要一些建议。数据表如下......

(DataPoint表)

id     datetime
_____________________
1      2015-09-08 21:00:00
2      2015-09-08 21:00:01
3      2015-09-08 21:00:02
4      2015-09-08 21:00:03
5      2015-09-08 21:00:04

(SensorData表)

id     datapointId     SensorId     Temp    DateTime
_____________________________________________________
1      1               20           34.6    2015-09-08 21:00:00.345
2      1               21           34.2    2015-09-08 21:00:00.551
3      1               22           34.1    2015-09-08 21:00:00.101
4      1               41           34.3    2015-09-08 21:00:00.700
5      2               20           34.2    2015-09-08 21:00:01.223
6      2               21           34.4    2015-09-08 21:00:01.456
7      2               22           34.5    2015-09-08 21:00:01.100
8      2               41           34.6    2015-09-08 21:00:01.870

请注意,单个传感器DateTime和DataPoint DateTime不相等(但它们很接近)。这就是为什么我使用第二个表来让我能够进行粗略的并排比较而无需做一些模糊的dateTime逻辑。

我需要使用看起来像这样的结果数据集来查询此信息......

DateTime              Temp1    Temp2    Temp3
__________________________________________________
2015-09-08 21:00:00   34.5       34.1       41.1
2015-09-08 21:00:01   34.4       34.2       41.2
2015-09-08 21:00:02   34.4       34.2       41.2

我当前的SQL查询是(动态地)编写的......

SELECT DataPoint.DateTime,
max(case when SensorData.SensorId = 20 then SensorData.Temp end) Temp1,
max(case when SensorData.SensorId = 21 then SensorData.Temp end) Temp2,
max(case when SensorData.SensorId = 22 then SensorData.Temp end) Temp3,
FROM DataPoint LEFT JOIN SensorData ON DataPoint.Id=dbo.SensorData.DataPointId
WHERE DataPoint.DateTime BETWEEN [x] and [y]
GROUP BY DataPoint.DateTime ORDER BY DataPoint.DateTime

所以我的问题有三个部分:

1)为什么这个特定的查询这么慢?

2)是否有更好的方法来存储我丢失的信息?此时我还处于设计阶段。我选择了这种模式,因为我需要能够比较传感器的时间序列信息,这些传感器会以不规则的间隔发射数据。

3)是否有更快的方法来查询并将此数据转换为我想要的格式?

EDIT !!!对不起,我的查询结尾有一个GroupBy子句,我忘了添加。我的错。

2 个答案:

答案 0 :(得分:3)

  • 首先,您需要确保拥有DataPointId的索引,如果PK可能有索引,但如果是FK,则必须手动添加它。

  • 其次,您需要SensorIdDateTime的索引

  • 第三次在查询之前过滤SensorID,此时您正在处理所有百万条记录以生成报告

WHERE SensorID IN (20,21,22)

您也可以尝试PIVOT功能

<强> SqlFiddleDemo

SELECT [DateTime], [20] as Temp1, [21] as Temp2, [22] as Temp3
FROM
(SELECT [DateTime], SensorId, [Temp] 
 FROM sensor) AS SourceTable
PIVOT
(
MAX([Temp])
    FOR SensorId IN ([20], [21], [22])
) AS PivotTable;

答案 1 :(得分:-1)

我强烈建议使用&#34; GROUP BY&#34;这个条款。另外,从sensorData开始连接表。

类似的东西:

SELECT DP.DateTime, SD.SensorID, MAX(SD.Temp) as MaxTemp
FROM SensorData SD
LEFT JOIN DataPoint DP ON DP.ID = SD.DataPointID
WHERE DP.DateTime BETWEEN [x] and [x]
GROUP BY DP.DateTime, SD.SensorID

您将获得以下形式的数据: 日期,SensorID,MaxTemp 如果您需要将其转置为可视化,我建议(如果可能)使用数据透视表(Excel)。 (如果Excel不是一个选项;请告诉我;还有其他可能性。)