Sie müssen die Abfrage insgesamt umgestalten
Versuchen Sie, die WHERE-Klauseln früher und die JOINs später auszuführen
Select Count(1) from DetailsTable dt
join (Select UserId,Id FROM MasterTable where
created between @date1 and @date2) mt on mt.Id = dt.MasterId
join (Select Id FROM UserTable WHERE Role is NULL) ut
on ut.Id = mt.UserId;
Selbst wenn Sie einen EXPLAIN-Plan für diese überarbeitete Abfrage ausführen und es schlechter aussieht als Ihr Original, versuchen Sie es trotzdem. Die intern erstellten temporären Tabellen führen kartesische Verknüpfungen durch, die Tabellen, mit denen gearbeitet werden soll, sind jedoch kleiner.
Ich habe diese Idee aus diesem YouTube-Video .
Ich habe die Prinzipien des Videos in einer sehr komplexen Frage in StackOverflow ausprobiert und bekam 200 Punkte Kopfgeld.
@gbn erwähnte, dass sichergestellt werden muss, dass die richtigen Indizes vorhanden sind. In diesem Fall indizieren Sie bitte die erstellte Spalte in MasterTable.
Versuche es !!!
UPDATE 2011-06-24 22:31 EDT
Sie sollten diese Abfragen ausführen:
SELECT COUNT(1) AllRoles FROM UserTable;
SELECT COUNT(1) NullRoles FROM UserTable WHERE Role is NULL;
Wenn NullRoles X 20 <AllRoles (mit anderen Worten, wenn NullRoles weniger als 5% der Tabellenzeilen beträgt), sollten Sie einen nicht eindeutigen Index für die Rolle in UserTable erstellen. Andernfalls würde eine vollständige Tabelle mit UserTable ausreichen, da das Abfrageoptimierungsprogramm möglicherweise die Verwendung eines Indexes ausschließt.
UPDATE 2011-06-25 12:40 EDT
Da ich ein MySQL-DBA bin, erfordert meine Methode, dem MySQL-Abfrageoptimierer durch positiven Pessimismus nicht zu vertrauen und konservativ zu sein. Daher werde ich versuchen, eine Abfrage umzugestalten oder die erforderlichen Abdeckungsindizes zu erstellen, um die verborgenen schlechten Gewohnheiten des MySQL Query Optimizer zu überwinden. Die Antwort von @ gbn scheint vollständiger zu sein, da SQL Server bei der Bewertung von Abfragen möglicherweise mehr "Verstandeskraft" besitzt.