Ich habe eine Tabelle, die einige grundlegende Daten über Besucher Sitzungen auf Websites von Drittanbietern speichert. Dies ist seine Struktur:Mysql-Index-Optimierung für eine Tabelle mit mehreren Indizes, die einige der gleichen Spalten indexieren
id, site_id, unixtime, unixtime_last, ip_address, uid
Es vier Indizes sind: id
, site_id/unixtime
, site_id/ip_address
und site_id/uid
Es gibt viele verschiedene Arten von Möglichkeiten, wie wir diese Tabelle abzufragen, und alle von ihnen sind spezifisch für die Webseitenadresse. Der Index mit unixtime wird verwendet, um die Liste der Besucher für ein bestimmtes Datum oder einen bestimmten Zeitraum anzuzeigen. Die anderen beiden werden verwendet, um alle Besuche von einer IP-Adresse oder einer "UID" zu finden (ein eindeutiger Cookie-Wert, der für jeden Besucher erstellt wurde), und um zu bestimmen, ob dies ein neuer Besucher oder ein wiederkehrender Besucher ist.
Offensichtlich Speichern von site_id in 3 Indizes ist ineffizient für Schreibgeschwindigkeit und Speicher, aber ich sehe keine Möglichkeit, da ich in der Lage sein, diese Daten für eine bestimmte Site-ID schnell abzufragen.
Irgendwelche Ideen, um dies effizienter zu machen?
Ich verstehe nicht wirklich B-Bäume neben einigen sehr grundlegenden Sachen, aber es ist effizienter, die linke Spalte eines Index der mit der geringsten Varianz zu haben - richtig? Weil ich dachte, dass die site_id die zweite Spalte des Indexes für ip_address und uid ist, aber ich denke, das würde den Index weniger effizient machen, da die IP und UID mehr variieren als die Site ID, weil wir nur ungefähr 8000 haben einzigartige Websites pro Datenbankserver, aber täglich Millionen von einzigartigen Besuchern auf allen ~ 8000 Websites.
Ich habe auch darüber nachgedacht, site_id aus den IP- und UID-Indizes vollständig zu entfernen, da die Chancen, dass der gleiche Besucher zu mehreren Sites mit demselben Datenbankserver geht, ziemlich gering sind, aber in Fällen, in denen dies passiert, befürchte ich Es könnte ziemlich langsam sein, festzustellen, ob dies ein neuer Besucher dieser site_id ist oder nicht. Die Abfrage wäre so etwas wie:
select id from sessions where uid = 'value' and site_id = 123 limit 1
... also, wenn diese Besucher diese Seite zuvor besucht hatte, wäre es nur eine Zeile mit diesem site_id finden müssen, bevor sie gestoppt. Dies wäre nicht unbedingt schnell, aber akzeptabel schnell. Aber sagen wir, wir haben eine Seite, die 500.000 Besucher pro Tag erreicht, und ein bestimmter Besucher liebt diese Seite und fährt dort 10 Mal am Tag. Jetzt treffen sie zum ersten Mal eine andere Site auf demselben Datenbankserver. Die obige Abfrage kann ziemlich lange dauern, um alle potenziell Tausende von Zeilen für diese UID zu durchsuchen, die auf der gesamten Festplatte verstreut ist, da sie keine für diese Standort-ID finden würde.
Einsicht auf machen diese so effizient wie möglich würde :)
-Update erkannt werden - das ist eine MyISAM-Tabelle mit MySQL 5.0. Meine Bedenken betreffen sowohl die Leistung als auch den Speicherplatz. Diese Tabelle liest und schreibt schwer. Wenn ich zwischen Leistung und Speicher wählen sollte, ist Leistung meine größte Sorge - aber beide sind wichtig.
Wir verwenden memcached stark in allen Bereichen unseres Dienstes, aber das ist keine Entschuldigung, sich nicht um das Datenbankdesign zu kümmern. Ich möchte, dass die Datenbank so effizient wie möglich ist.
Speichermodul? MySQL-Version? Und wie möchten Sie dies effizienter machen - disk-Nutzung oder Leistung? Und haben Sie tatsächliche Probleme zu lösen oder ist das nur eine rhetorische Frage? – ggiroux
mysql 5.0, myisam engine. Es geht mir sowohl um Speicherplatz als auch um Performance, da es sich sowohl um eine Lese- als auch um eine Write-Tabelle handelt. Ja, tatsächliches Problem. :) – Sean
Haben Sie High Performance MySQL gelesen? –