Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie sollte ich vorgehen, um eine Abfrage mit zwei Bereichsbedingungen zu indizieren?

IN liegt sozusagen zwischen = und eine "Reichweite". Also streite ich mit dem Titel der Frage. Zwei Bereiche zu optimieren ist praktisch unmöglich; ein IN plus eine Reihe hat eine Chance auf Optimierung.

Basierend auf

WHERE `StartedAt` >= FROM_UNIXTIME(1518990000)  
AND   `StartedAt` <  FROM_UNIXTIME(1518998400) 
AND `DeviceId` IN (
    UNHEX('00030000000000000000000000000000'),
    UNHEX('000300000000000000000000000181cd'),
    UNHEX('000300000000000000000000000e7cf6'),
    UNHEX('000300000000000000000000000e7cf7'),
    UNHEX('000300000000000000000000000f423f')
) AND `MarkedForDeletion` = FALSE

Ich würde 2 Indizes bereitstellen und den Optimierer entscheiden lassen, welcher verwendet werden soll:

INDEX(MarkedForDeletion, StartedAt, DeviceId)
INDEX(MarkedForDeletion, DeviceId, StartedAt)

Einige neuere Versionen von MySQL/MariaDB können alle 3 Spalten in der zweiten überspringen und verwenden Index. In allen Versionen machen die ersten 2 Spalten jedes Indexes ihn zu einem Kandidaten. Die Wahl kann von Statistiken bestimmt werden und kann (oder auch nicht) die „richtige“ Wahl sein.

Seit AlarmId darf nicht NULL sein , verwenden Sie das Muster:COUNT(*) .

Nach dieser Änderung ist jeder meiner Indizes "deckend", wodurch die Leistung zusätzlich gesteigert wird.