如何优化缓慢的SQL查询?
我有两张桌子。第一个“用户”表由记录用户登录事件的行组成。该表如下所示:如何优化缓慢的SQL查询?,sql,sql-server,Sql,Sql Server,我有两张桌子。第一个“用户”表由记录用户登录事件的行组成。该表如下所示: LoginTable LoginID Name Time 100 Joe 12:00pm 101 Bob 3:30pm 102 Joe 4:00pm 103 Sue 6:15pm MetricsTable MetricID LoginID Label Data 500 100 IPAddre
LoginTable
LoginID Name Time
100 Joe 12:00pm
101 Bob 3:30pm
102 Joe 4:00pm
103 Sue 6:15pm
MetricsTable
MetricID LoginID Label Data
500 100 IPAddress 1.2.3.4
501 100 Attempts 25
502 100 Status Good
503 101 IPAddress 1.2.3.5
504 101 Attempts 19
505 101 Status Bad
506 102 IPAddress 1.2.3.6
507 102 Attempts 35
508 102 Status Hold
509 103 IPAddress 1.2.3.7
510 103 Attempts 4
511 103 Status Trial
SELECT LoginTable.LoginID, LoginTable.Name, LoginTable.Time,
(SELECT MetricsTable.Data FROM MetricsTable WHERE
MetricsTable.LoginID=LoginTable.LoginID and
MetricsTable.Label="IPAddress") as IPAddressEx
FROM LoginTable
LoginID Name Time IP Attempts Status FutureColumn1 FutureColumn2 ...
第二个表记录了关于每个登录的附加指标,虽然不常见,但记录的附加项的数量可能会发生变化。该表如下所示:
LoginTable
LoginID Name Time
100 Joe 12:00pm
101 Bob 3:30pm
102 Joe 4:00pm
103 Sue 6:15pm
MetricsTable
MetricID LoginID Label Data
500 100 IPAddress 1.2.3.4
501 100 Attempts 25
502 100 Status Good
503 101 IPAddress 1.2.3.5
504 101 Attempts 19
505 101 Status Bad
506 102 IPAddress 1.2.3.6
507 102 Attempts 35
508 102 Status Hold
509 103 IPAddress 1.2.3.7
510 103 Attempts 4
511 103 Status Trial
SELECT LoginTable.LoginID, LoginTable.Name, LoginTable.Time,
(SELECT MetricsTable.Data FROM MetricsTable WHERE
MetricsTable.LoginID=LoginTable.LoginID and
MetricsTable.Label="IPAddress") as IPAddressEx
FROM LoginTable
LoginID Name Time IP Attempts Status FutureColumn1 FutureColumn2 ...
我试图构建一个LoginTable查询,该查询将为每一行显示表示与每个登录事件关联的额外度量数据的附加列
一种解决方案是这样做:
LoginTable
LoginID Name Time
100 Joe 12:00pm
101 Bob 3:30pm
102 Joe 4:00pm
103 Sue 6:15pm
MetricsTable
MetricID LoginID Label Data
500 100 IPAddress 1.2.3.4
501 100 Attempts 25
502 100 Status Good
503 101 IPAddress 1.2.3.5
504 101 Attempts 19
505 101 Status Bad
506 102 IPAddress 1.2.3.6
507 102 Attempts 35
508 102 Status Hold
509 103 IPAddress 1.2.3.7
510 103 Attempts 4
511 103 Status Trial
SELECT LoginTable.LoginID, LoginTable.Name, LoginTable.Time,
(SELECT MetricsTable.Data FROM MetricsTable WHERE
MetricsTable.LoginID=LoginTable.LoginID and
MetricsTable.Label="IPAddress") as IPAddressEx
FROM LoginTable
LoginID Name Time IP Attempts Status FutureColumn1 FutureColumn2 ...
该查询将显示一个额外的列,其中显示为该事件记录的“IPAddress”值。然后,我可以再添加两个子查询,以显示“尝试”和“状态”的附加列(请注意,这些只是假的示例)。我不关心是否能够自动识别更多的潜在列,如果它们出现,我可以手动添加它们。然而,这种为每一个额外列添加子查询的技术似乎非常缓慢
实现这一目标的更好方法是什么
请假设我无法重组表
谢谢 听起来您需要这样的结果集:
LoginTable
LoginID Name Time
100 Joe 12:00pm
101 Bob 3:30pm
102 Joe 4:00pm
103 Sue 6:15pm
MetricsTable
MetricID LoginID Label Data
500 100 IPAddress 1.2.3.4
501 100 Attempts 25
502 100 Status Good
503 101 IPAddress 1.2.3.5
504 101 Attempts 19
505 101 Status Bad
506 102 IPAddress 1.2.3.6
507 102 Attempts 35
508 102 Status Hold
509 103 IPAddress 1.2.3.7
510 103 Attempts 4
511 103 Status Trial
SELECT LoginTable.LoginID, LoginTable.Name, LoginTable.Time,
(SELECT MetricsTable.Data FROM MetricsTable WHERE
MetricsTable.LoginID=LoginTable.LoginID and
MetricsTable.Label="IPAddress") as IPAddressEx
FROM LoginTable
LoginID Name Time IP Attempts Status FutureColumn1 FutureColumn2 ...
你可以,或者你的数据
Select LoginID,
Name,
Time,
[IPAddress],
[Attempts],
[Status]
From (Select LoginTable.LoginID,
LoginTable.Name,
LoginTable.Time,
MetricsTable.Data,
MetricsTable.Label
From LoginTable
Inner Join MetricsTable
ON MetricsTable.LoginID=LoginTable.LoginID) As nested
Pivot (Min(Data) For Label In ([IPAddress],[Attempts],[Status])) As PivotTable
我没有时间来测试这一点,而且我也不是最擅长使用即时数据透视的人,但我认为这是正确的。与Andrew的答案类似,我将改为将MetricsTable命名为MetricsTable
SELECT LoginTable.LoginID
,LoginTable.Name
,LoginTable.Time
,IPAddress= IPAddress.Data
,Attempts = Attempts.Data
FROM LoginTable
Left Join MetricsTable As IPAddress
On IPAddress.LoginID=LoginTable.LoginID
And IPAddress.Label="IPAddress"
Left Join MetricsTable As Attempts
On Attempts.LoginID=LoginTable.LoginID
And Attempts.Label="Attempts"
-- Other joins for additional stats
如果您知道某些信息(如IPAddress)始终可用,请使用内部联接
而不是左联接
您可以按照Love2Learn的建议查看数据,但如果可能,我更喜欢直接连接
此外,如果LoginID不是LoginTable上的主键,则其上的索引将提高读取速度
同样,如果您在MetricsTable.LoginID上没有索引,我强烈建议您这样做
通过上面的查询,MetricsTable上的一个有用索引将位于LoginID和Label上(按该顺序),并且可能包含数据,以便数据库引擎可以从索引中读取所有数据。您应该进行性能测试,看看索引的开销是否值得。您没有提到索引。您是否有,在哪些列上,以及上次重建/重新组织它们的时间?统计数据是最新的吗?你能展示一下查询的解释计划吗?为什么你不能简单地连接两个表呢?我只是说查询速度非常慢,因为任何人都可以看到它,并意识到它将永远无法运行。所以实际上我的问题不是速度,而是如何写得更好。下面涉及PIVOT的答案是我需要的方向,我不知道PIVOT的动作。我问这个问题,因为我不是一个MS SQL专家,我的驾驶室是C,C++,MFC,.NET WiFrms,JavaScript…不管怎样,我不可能一直都知道所有的事情,这就是为什么…尽管有聪明的反对票。。。吼叫声尝试下面的建议,然后标出答案。