2

OR クエリのパフォーマンスを向上させるために使用できるクエリ ヒントの種類。

以下の 2 つのクエリは個別に即座に実行され、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% を占める) を使用していることがわかります。

アップデート:

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
4

1 に答える 1

1

クエリのヒントを求めていることは知っていますが、ユニオンを使用して2つのクエリとして実行することもできます

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 を使用すると、一度に 1 つずつ実行され、クエリ オプティマイザーが愚かになる可能性が少なくなります。

于 2013-05-07T15:40:02.383 に答える