- Wann sollte ich einen zusammengesetzten Index in einer Datenbank verwenden?
- Was sind die Leistungsauswirkungen bei Verwendung eines zusammengesetzten Index?
- Warum sollte ich einen zusammengesetzten Index verwenden?
Zum Beispiel habe ich eine homes
Tabelle:
CREATE TABLE IF NOT EXISTS `homes` (
`home_id` int(10) unsigned NOT NULL auto_increment,
`sqft` smallint(5) unsigned NOT NULL,
`year_built` smallint(5) unsigned NOT NULL,
`geolat` decimal(10,6) default NULL,
`geolng` decimal(10,6) default NULL,
PRIMARY KEY (`home_id`),
KEY `geolat` (`geolat`),
KEY `geolng` (`geolng`),
) ENGINE=InnoDB ;
Macht es Sinn, für mich einen zusammengesetzten Index für beide verwendet , um geolat
und geolng
, so dass:
Ich ersetze:
KEY `geolat` (`geolat`),
KEY `geolng` (`geolng`),
mit:
KEY `geolat_geolng` (`geolat`, `geolng`)
Wenn ja:
- Warum?
- Was ist die Leistungsbeeinträchtigung durch Verwendung eines zusammengesetzten Index?
AKTUALISIEREN:
Da viele Leute angegeben haben, dass dies vollständig von den von mir durchgeführten Abfragen abhängt, wird im Folgenden die am häufigsten durchgeführte Abfrage aufgeführt:
SELECT * FROM homes
WHERE geolat BETWEEN ??? AND ???
AND geolng BETWEEN ??? AND ???
UPDATE 2:
Mit folgendem Datenbankschema:
CREATE TABLE IF NOT EXISTS `homes` (
`home_id` int(10) unsigned NOT NULL auto_increment,
`primary_photo_group_id` int(10) unsigned NOT NULL default '0',
`customer_id` bigint(20) unsigned NOT NULL,
`account_type_id` int(11) NOT NULL,
`address` varchar(128) collate utf8_unicode_ci NOT NULL,
`city` varchar(64) collate utf8_unicode_ci NOT NULL,
`state` varchar(2) collate utf8_unicode_ci NOT NULL,
`zip` mediumint(8) unsigned NOT NULL,
`price` mediumint(8) unsigned NOT NULL,
`sqft` smallint(5) unsigned NOT NULL,
`year_built` smallint(5) unsigned NOT NULL,
`num_of_beds` tinyint(3) unsigned NOT NULL,
`num_of_baths` decimal(3,1) unsigned NOT NULL,
`num_of_floors` tinyint(3) unsigned NOT NULL,
`description` text collate utf8_unicode_ci,
`geolat` decimal(10,6) default NULL,
`geolng` decimal(10,6) default NULL,
`display_status` tinyint(1) NOT NULL,
`date_listed` timestamp NOT NULL default CURRENT_TIMESTAMP,
`contact_email` varchar(100) collate utf8_unicode_ci NOT NULL,
`contact_phone_number` varchar(15) collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`home_id`),
KEY `customer_id` (`customer_id`),
KEY `city` (`city`),
KEY `num_of_beds` (`num_of_beds`),
KEY `num_of_baths` (`num_of_baths`),
KEY `geolat` (`geolat`),
KEY `geolng` (`geolng`),
KEY `account_type_id` (`account_type_id`),
KEY `display_status` (`display_status`),
KEY `sqft` (`sqft`),
KEY `price` (`price`),
KEY `primary_photo_group_id` (`primary_photo_group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=8 ;
Verwenden des folgenden SQL:
EXPLAIN SELECT homes.home_id,
address,
city,
state,
zip,
price,
sqft,
year_built,
account_type_id,
num_of_beds,
num_of_baths,
geolat,
geolng,
photo_id,
photo_url_dir
FROM homes
LEFT OUTER JOIN home_photos ON homes.home_id = home_photos.home_id
AND homes.primary_photo_group_id = home_photos.home_photo_group_id
AND home_photos.home_photo_type_id = 2
WHERE homes.display_status = true
AND homes.geolat BETWEEN -100 AND 100
AND homes.geolng BETWEEN -100 AND 100
EXPLAIN gibt zurück:
id select_type table type possible_keys key key_len ref rows Extra
----------------------------------------------------------------------------------------------------------
1 SIMPLE homes ref geolat,geolng,display_status display_status 1 const 2 Using where
1 SIMPLE home_photos ref home_id,home_photo_type_id,home_photo_group_id home_photo_group_id 4 homes.primary_photo_group_id 4
Ich verstehe nicht ganz, wie man den EXPLAIN-Befehl liest. Sieht das gut oder schlecht aus? Im Moment verwende ich KEINEN zusammengesetzten Index für Geolat und Geolng. Sollte ich sein?
quelle
WHERE geolat BETWEEN ??? AND ??? AND geolng BETWEEN ??? AND ???
. Es stoppt nach dem ersten Feld. Die Antwort von "Fragenüberlauf" erklärt warum.Stellen Sie sich vor, Sie haben die folgenden drei Fragen:
Abfrage I:
Abfrage II:
Abfrage III:
Wenn Sie einen separaten Index pro Spalte haben, verwenden alle drei Abfragen Indizes. Wenn Sie in MySQL über einen zusammengesetzten Index (
geolat
,geolng
) verfügen , verwenden nur Abfrage I und Abfrage II (die den ersten Teil des zusammengesetzten Index verwendet) Indizes. In diesem Fall erfordert Abfrage III eine vollständige Tabellensuche.Im Abschnitt Mehrspaltenindizes des Handbuchs wird klar erklärt, wie Mehrspaltenindizes funktionieren, daher möchte ich das Handbuch nicht erneut eingeben.
Auf der Seite des MySQL-Referenzhandbuchs :
Wenn Sie einen getrennten Index für Geolat- und Geolng-Spalten verwenden, haben Sie zwei verschiedene Indizes in Ihrer Tabelle, die Sie unabhängig voneinander durchsuchen können.
Wenn Sie einen zusammengesetzten Index verwenden, haben Sie nur einen Index für beide Spalten:
RRN ist die relative Datensatznummer (zur Vereinfachung können Sie ID sagen). Die ersten beiden Indizes werden separat generiert und der dritte Index ist zusammengesetzt. Wie Sie sehen können, können Sie basierend auf geolng auf zusammengesetztem suchen, da es nach geolat indiziert ist. Es ist jedoch möglich, nach geolat oder "geolat AND geolng" zu suchen (da geolng ein Index der zweiten Ebene ist).
Schauen Sie sich auch den Abschnitt Wie MySQL verwendet Indizes an .
quelle
BETWEEN
), werden keine weiteren Felder des Index berücksichtigt! Der zusammengesetzte Index ist also nicht besser.Es könnte ein Missverständnis darüber bestehen, was der zusammengesetzte Index tut. Viele Leute denken, dass der zusammengesetzte Index verwendet werden kann, um eine Suchabfrage zu optimieren, solange die
where
Klausel die indizierten Spalten abdeckt, in Ihrem Fallgeolat
undgeolng
. Lassen Sie uns tiefer gehen:Ich glaube, Ihre Daten zu den Koordinaten von Häusern wären zufällige Dezimalstellen als solche:
Da
geolat
undgeolng
Werte wiederholen sich kaum. Ein zusammengesetzter Index fürgeolat
undgeolng
würde ungefähr so aussehen:Daher ist die zweite Spalte des zusammengesetzten Index grundsätzlich unbrauchbar ! Die Geschwindigkeit Ihrer Abfrage mit einem zusammengesetzten Index wird wahrscheinlich einem Index nur für die
geolat
Spalte ähnlich sein .Wie von Will erwähnt, bietet MySQL Unterstützung für räumliche Erweiterungen . Ein räumlicher Punkt wird in einer einzelnen Spalte anstelle von zwei separaten
lat
lng
Spalten gespeichert . Der räumliche Index kann auf eine solche Spalte angewendet werden. Die Effizienz könnte jedoch aufgrund meiner persönlichen Erfahrung überbewertet werden. Es könnte sein, dass der räumliche Index das zweidimensionale Problem nicht löst, sondern lediglich die Suche mithilfe von R-Bäumen mit quadratischer Aufteilung beschleunigt .Der Nachteil ist, dass ein räumlicher Punkt viel mehr Speicher benötigt, da er 8-Byte-Zahlen mit doppelter Genauigkeit zum Speichern von Koordinaten verwendet. Korrigieren Sie mich, wenn ich falsch liege.
quelle
Zusammengesetzte Indizes sind sehr leistungsfähig, da sie:
STRUKTURINTEGRITÄT DURCHSETZEN
Zusammengesetzte Indizes sind nicht nur eine andere Art von Index. Sie können einer Tabelle die erforderliche Struktur bereitstellen, indem sie die Integrität als Primärschlüssel erzwingen.
Innodb von MySQL unterstützt Clustering. Das folgende Beispiel zeigt, warum möglicherweise ein zusammengesetzter Index erforderlich ist.
Um die Tabellen eines Freundes zu erstellen (dh für ein soziales Netzwerk), benötigen wir zwei Spalten :
user_id, friend_id
.Tischstruktur
Aufgrund dessen ist ein Primärschlüssel (PK) eindeutig. Durch Erstellen einer zusammengesetzten PK überprüft Innodb automatisch, ob beim Hinzufügen
user_id, friend_id
eines neuen Datensatzes keine Duplikate vorhanden sind. Dies ist das erwartete Verhalten, da kein Benutzer beispielsweise mehr als einen Datensatz (Beziehungslink) haben solltefriend_id = 2
.Ohne eine zusammengesetzte PK können wir dieses Schema mit einem Ersatzschlüssel erstellen:
Wenn nun ein neuer Datensatz hinzugefügt wird, müssen wir überprüfen, ob es sich um einen vorherigen Datensatz mit der Kombination handelt
user_id, friend_id
noch nicht vorhanden ist.Daher kann ein zusammengesetzter Index die Strukturintegrität erzwingen.
SORTIEREN AUF EINEM GEFILTERTEN Ausweis AKTIVIEREN
Es ist sehr üblich, eine Reihe von Datensätzen nach der Zeit des Posts (Zeitstempel oder Datum / Uhrzeit) zu sortieren. Normalerweise bedeutet dies das Posten auf einer bestimmten ID. Hier ist ein Beispiel
Tabelle User_Wall_Posts (überlegen Sie, ob Facebooks Pinnwandeinträge)
Wir möchten alle Beiträge abfragen und finden
user_id = 10
und die Kommentarbeiträge nach sortierentimestamp
(Datum) .SQL-Abfrage
Mit der zusammengesetzten PK kann MySQL die Ergebnisse anhand des Index filtern und sortieren. MySQL muss keine temporäre Datei oder Dateisortierung verwenden, um die Ergebnisse abzurufen. Ohne einen zusammengesetzten Schlüssel wäre dies nicht möglich und würde eine sehr ineffiziente Abfrage verursachen.
Daher sind zusammengesetzte Schlüssel sehr leistungsfähig und passen mehr als das einfache Problem "Ich möchte suchen,
column_a, column_b
damit ich zusammengesetzte Schlüssel verwenden kann. Für mein aktuelles Datenbankschema habe ich genauso viele zusammengesetzte Schlüssel wie einzelne Schlüssel. Nicht übersehen." Verwendung eines zusammengesetzten Schlüssels!quelle
Zusammengesetzte Indizes sind nützlich für
Ein zusammengesetzter Index kann nicht zwei Bereiche verarbeiten. Ich diskutiere dies weiter in meinem Index-Kochbuch .
Nächste finden - Wenn es wirklich um Optimierung geht
dann kann kein Index wirklich beide Dimensionen verarbeiten.
Stattdessen muss man über den Tellerrand hinaus denken. Wenn eine Dimension über Partitionierung implementiert wird und die andere durch sorgfältige Auswahl der Dimension implementiert wird
PRIMARY KEY
, kann eine sehr bessere Effizienz für sehr große Tabellen mit lat / lng-Suche erzielt werden. In meinem latlng-Blog geht es um die Implementierung von "find next" auf der ganzen Welt. Es enthält Code.Das
PARTITIONs
sind Streifen von Breitengraden. DasPRIMARY KEY
beginnt absichtlich mit dem Längengrad, so dass sich die nützlichen Zeilen wahrscheinlich im selben Block befinden. Eine gespeicherte Routine orchestriert den unordentlichen Code dafürorder by... limit...
um das "Quadrat" um das Ziel herum zu vergrößern, bis Sie genügend Coffeeshops (oder was auch immer) haben. Es kümmert sich auch um die Großkreisberechnungen und den Umgang mit der Datenlinie und den Polen.Mehr
Ich habe einen anderen Blog geschrieben; Es werden 5 Arten der Lat / Lng-Suche verglichen: http://mysql.rjweb.org/doc.php/latlng#representation_choices (Es verweist auf den oben angegebenen Link als eine der 5.) Eine der anderen Möglichkeiten ist diese: und es weist darauf hin, dass sie für den speziellen Fall optimal sind :
Das heißt, es ist wichtig , beide Spalten in zwei Indizes zu haben und keine einspaltigen Indizes für Geolat und Geolng zu haben.
quelle
Es gibt kein Schwarz und Weiß, eine Größe passt zu allen Antworten.
Sie sollten einen zusammengesetzten Index verwenden, wenn Ihre Abfragearbeitslast von einem profitieren würde.
Sie müssen Ihre Abfragearbeitslast profilieren, um dies festzustellen.
Ein zusammengesetzter Index kommt ins Spiel, wenn Abfragen vollständig von diesem Index aus erfüllt werden können.
UPDATE (als Antwort auf die Bearbeitung der geposteten Frage): Wenn Sie * aus der Tabelle auswählen, kann der zusammengesetzte Index verwendet werden, möglicherweise nicht. Sie müssen EXPLAIN PLAN ausführen , um sicherzugehen.
quelle
Für räumliche Suchen benötigen Sie einen R-Baum Algorithmus, mit dem Sie sehr schnell nach geografischen Gebieten suchen können. Genau das, was Sie für diesen Job brauchen.
In einigen Datenbanken sind räumliche Indizes integriert. Eine schnelle Google-Suche zeigt, dass MySQL 5 über diese verfügt (wenn Sie sich SQL ansehen, schätze ich, dass Sie MySQL verwenden).
quelle
Der zusammengesetzte Index kann hilfreich sein, wenn Sie die
group by
Klausel optimieren möchten (siehe diesen Artikel http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html ). Bitte pass auf:quelle
GROUP BY
wurde nicht erwähnt.GROUP BY
wurde vom OP nicht erwähnt.Ich bin bei @Mitch, hängt ganz von Ihren Fragen ab. Glücklicherweise können Sie jederzeit Indizes erstellen und löschen und Ihren Abfragen das Schlüsselwort EXPLAIN voranstellen, um festzustellen, ob der Abfrageanalysator die Indizes verwendet.
Wenn Sie ein genaues Lat / Long-Paar suchen, ist dieser Index wahrscheinlich sinnvoll. Aber Sie werden wahrscheinlich nach Häusern in einer bestimmten Entfernung von einem bestimmten Ort suchen, sodass Ihre Fragen ungefähr so aussehen (siehe Quelle ):
und der Index wird sehr wahrscheinlich überhaupt nicht hilfreich sein. Für Geospatial - Abfragen, müssen Sie so etwas wie dieses .
Update: mit dieser Abfrage:
Der Abfrageanalysator kann einen Index nur für Geolat oder einen Index nur für Geolng oder möglicherweise beide Indizes verwenden. Ich denke nicht, dass es einen zusammengesetzten Index verwenden würde. Es ist jedoch einfach, jede dieser Permutationen an einem realen Datensatz auszuprobieren und dann (a) zu sehen, was EXPLAIN Ihnen sagt, und (b) die Zeit zu messen, die die Abfrage wirklich benötigt.
quelle