2013-05-07 84 views
1

我可以使用什么样的查询提示来改进OR查询的性能。TSQL OR查询计划提示

单独地,下面的两个查询立即运行并返回0行。

SELECT * FROM AuditInfo ai 
WHERE (ai.AppointmentIdForChange = 60231) 
and ai.objectname = 'dbo.Appointments' 

SELECT * FROM AuditInfo ai 
WHERE (ai.AppointmentIdForKey = 60231) 
and ai.objectname = 'dbo.Appointments' 

AuditInfo是一个视图。

但是下面的查询将永远运行下去(10+分钟)

SELECT * FROM AuditInfo ai 
WHERE (ai.AppointmentIdForKey= 60231 OR ai.AppointmentIdForChange = 60231) 
and ai.objectname = 'dbo.Appointments' 

我该如何提高呢?有没有查询提示我可以使用?

在估计的执行计划中,我可以看到各个查询使用密钥查找,而带有OR语句的查询使用索引查找(占74%的成本)。

UPDATE:

的AuditInfo视图的定义如下:

ALTER VIEW AuditInfo 
AS 
SELECT 
    ae.Id 
    ,ae.AuditDateTime AS DateTime 
    ,ae.ChangeTypeId 
    ,ae.ObjectName 
    ,aek.KeyName 
    ,aek.KeyValue 
    ,aek.KeyValueNumeric 
    ,ae.UserId 
    ,ae.HostName 
    ,ae.ServerName 
    ,aec.OldValue 
    ,(SELECT TOP 1 aecNewValue.OldValue AS Value 
     FROM dbo.AuditEntries aeNewValue 
     JOIN dbo.AuditEntryKeyValues aekNewValue ON aeNewValue.Id = aekNewValue.AuditEntryId AND aek.KeyName = aekNewValue.KeyName AND aek.KeyValueNumeric = aekNewValue.KeyValueNumeric 
     JOIN dbo.AuditEntryChanges aecNewValue ON aeNewValue.Id = aecNewValue.AuditEntryId AND aec.ColumnName = aecNewValue.ColumnName 
     WHERE aeNewValue.ChangeTypeId IN (0, 1) AND aeNewValue.AuditDateTime > ae.AuditDateTime AND aeNewValue.ObjectName = ae.ObjectName 
     ORDER BY aeNewValue.AuditDateTime 
    ) AS NewValue 
    ,appointmentForKey.AppointmentId AS AppointmentIdForKey, appointmentForChange.AppointmentId AS AppointmentIdForChange 
FROM dbo.AuditEntries ae 
JOIN dbo.AuditEntryKeyValues aek on ae.Id = aek.AuditEntryId 
LEFT JOIN dbo.AuditEntryChanges aec on ae.Id = aec.AuditEntryId AND aec.ColumnName IN ('PatientId', 'AppointmentId') 

-- Get AppointmentId 
LEFT JOIN dbo.Appointments appointmentForKey ON aek.KeyName = 'AppointmentId' AND aek.KeyValueNumeric = appointmentForKey.AppointmentId 
LEFT JOIN dbo.Appointments appointmentForChange ON aec.ColumnName = 'AppointmentId' AND aec.OldValueNumeric = appointmentForChange.AppointmentId 

GROUP BY ae.Id, ae.AuditDateTime, ae.UserId, ae.ChangeTypeId, ae.ObjectName, ae.HostName, ae.ServerName, aek.KeyName, aek.KeyValue, aek.KeyValueNumeric, aec.OldValueNumeric, aec.OldValue, aec.ColumnName 
,appointmentForKey.AppointmentId, appointmentForChange.AppointmentId 
+0

“AppointmentIdForKey”,“AppointmentIdForChange”和“objectname”是否已编入索引? – 2013-05-07 15:34:24

+0

它们都对应于两个不同表上的索引列。 – Jeff 2013-05-07 15:36:59

+0

我们在这里聊什么大小的桌子?我假设'AppointmentIdForChange'和'AppointmentIdForKey'类型是'INT','objectname'是'VARCHAR'或'NVARCHAR'? – 2013-05-07 15:41:45

回答

1

我知道你问的查询提示,但你可以只用一个工会

SELECT * FROM AuditInfo ai 
WHERE (ai.AppointmentIdForChange = 60231) 
and ai.objectname = 'dbo.Appointments' 
UNION 
SELECT * FROM AuditInfo ai 
WHERE (ai.AppointmentIdForKey = 60231) 
and ai.objectname = 'dbo.Appointments' 
运行它的两个查询

明天表演吧。
我会通过JOIN或OR来获得UNION以获得稳定性。
使用Union SQL一次只能处理它们,而查询优化器变得愚蠢的可能性更小。

+0

联合执行与OR相同的操作。 UNION ALL可以正常工作,但不会产生所需的结果。 SELECT DISTINCT * FROM(... UNION ALL ...)的作品...但有点详细 – Jeff 2013-05-07 15:42:43

+0

因此,DISTINCT * FROM(... UNION ALL ...)的作品。 10分钟下降到秒的一小部分,但你是否因为它冗长而不予理睬? – Paparazzi 2013-05-07 20:28:40

+0

不排除它......我只是想弄清楚它为什么会起作用,或许我可以如何强制执行期望的计划,这种执行计划明显加上工会似乎都会产生......执行计划似乎如此不稳定的事实让我担心依赖作为解决方案。 。 – Jeff 2013-05-08 03:04:58