2016-03-21 2 views
2

Ich habe Tabelle speichern Telefonnummern mit 800M Zeilen.Suche 1 Zeile Daten auf BigTable 800'000'000 Reihe MariaDB InnoDB

column 
region_code_id smallint(4) unsigned YES   
local_number mediumint(7) unsigned YES   
region_id  smallint(4) unsigned YES   
operator_id  smallint(4) unsigned YES   
id int(10)  unsigned  NO PRI  auto_increment 

Ich brauche number.id zu finden, wo region_code_id = 119 and localnumber = 1234567

select * from numbers where numbers.region_code_id = 119 and numbers.local_number = 1234567; 

diese Abfrage über 600 Sekunden auszuführen. Wie kann ich es verbessern?

UPDATE

Dank für unswer, verstehe ich, i Index für diese Spalte benötigen, versuche ich diese, sobald ich den Server mit mehr SSD bekommen, jetzt kostenlos 1GB SSD Speicherplatz i. Wie kann ich herausfinden, wie viel Platz der Index einnimmt?

+1

Haben Sie einen Index für (region_code_id, local_number)? –

+0

Suchen Sie nach indizierten Spalten? Wie groß ist der Tisch und kann er in den Speicher für schnellere Suche passen? Wie lauten die Servereinstellungen für die Datenbank? Auf welcher Hardware läuft es? – gabe3886

Antwort

1

Für diese Abfrage:

select * 
from numbers 
where numbers.region_code_id = 119 and 
     numbers.local_number = 1234567; 

Sie möchten einen Index für numbers(region_code_id, local_number) oder numbers(local_number, region_code_id). Die Reihenfolge der Spalten spielt keine Rolle, da die Bedingungen für beide Spalten gleich sind.

create index idx_numbers_region_local on numbers(region_code_id, local_number); 
3

Betrachten INDEX auf Spalten hinzufügen, die Sie in WHERE-Klausel verwenden.

beginnen mit:

ALTER TABLE `numbers` 
    ADD INDEX `region_code_id_local_number` 
    (`region_code_id`, `local_number`); 

Hinweis: kann es einige Zeit dauern Index zu bauen.

Vor und nach dem Wechsel, führt Plan erklären zu vergleichen:

EXPLAIN EXTENDED select * from numbers where numbers.region_code_id = 119 and numbers.local_number = 1234567; 

Referenzen:

How MySQL uses indexes

+0

Danke, ich probiere das schon mal, sobald ich den Server mit mehr SSD bekomme, jetzt habe ich freien 1GB SSD Platz. Wie kann ich herausfinden, wie viel Platz der Index einnimmt? – berap

+0

Jetzt habe ich Index für ID Spalte https://yadi.sk/i/Mgd8eIHzqMXy9 kann ich es löschen, wenn eine ID nicht benötigt wird? – berap

+0

Ich würde 'PRIMARY' Schlüssel nicht fallen lassen. Erstellen Sie einen Dump/eine Sicherung der Datenbank, und importieren Sie sie erneut, nachdem Sie den freien Speicherplatz vergrößert haben. – rkosegi

0

Ich bin damit einverstanden, dass INDEX(region_code_id, local_number) (in beliebiger Reihenfolge) für dieses Problem ist obligatorisch, aber Ich stecke meine Nase rein, um einen Schritt weiter zu gehen. Ist das Paar nicht "einzigartig"? Oder haben Sie doppelte Nummern in der Tabelle? Wenn es einzigartig ist, dann loswerden id und machen dieses Paar PRIMARY KEY(region_code_id, local_number). Die Tabelle wird möglicherweise nach der Änderung kleiner sein.

Zurück zu Ihrer Frage "wie groß". Wie groß ist der Tisch jetzt? Vielleicht 40 GB? Ein Sekundärindex (wie ursprünglich vorgeschlagen) würde wahrscheinlich über 20GB hinzufügen. Und Sie würden 20-60GB freien Speicherplatz benötigen, um die ALTER durchzuführen. Dies hängt davon ab, ob das Hinzufügen des Index in dieser Version "inplace" erfolgen kann.

Ändern der PK (wie ich vorschlagen) würde etwas weniger als 40 GB für die Tabelle ergeben. Es werden 40 GB freier Speicherplatz benötigt, um die ALTER durchzuführen.

Im Allgemeinen (und pessimistisch), planen Sie auf ALTER benötigen die sowohl die ursprüngliche Tabelle und die neue Tabelle, die auf Platte auf einmal sitzt. Dazu gehören vollständige Kopien der Daten und Index (e).

(A-Seite Frage: Sind Sie sicher, local_number überall auf 7 Stellen begrenzt ist)

Ein weiterer Ansatz für die Frage ... Für die Größe einer Tabelle oder ein Index in InnoDB Berechnung, fügen Sie die Datentyp-Größen bis (3 Bytes für , einige Durchschnitt für VARCHAR, usw.). Dann multiplizieren Sie mit der Anzahl der Zeilen. Dann multipliziere mit 4; Dadurch erhalten Sie ungefähr den benötigten Speicherplatz. (In der Regel ist 2-3 ausreichend für den letzten Multiplikator.)

Wenn die PK zu ändern, tun Sie es in einem Schritt:

ALTER TABLE foo 
    DROP PRIMARY KEY, 
    ADD PRIMARY KEY(region_code_id, local_number); 

Ändern der PK kann nicht "Inplace" erfolgen.

bearbeiten (meist für andere Leser)

@berap weist darauf hin, dass id für andere Zwecke benötigt wird. Daher ist es nicht möglich, id zu löschen und den PK zu wechseln.

Dies ist jedoch manchmal eine Option (vielleicht nicht in diesem Fall):

ALTER TABLE foo 
    DROP PRIMARY KEY, 
    ADD PRIMARY KEY(region_code_id, local_number), 
    ADD INDEX(id); 

Hinweise:

  • Die id..AUTO_INCREMENT wird weiterhin auch INDEX mit nur arbeiten.
  • Die fragliche SELECT wird effizienter sein, weil es die PK ist.
  • SELECT .. WHERE id = ... wird weniger effizient sein, weil id ein sekundärer Schlüssel ist.
  • Die Tabelle hat die gleiche Größe; der Sekundärschlüssel hätte auch die gleiche Größe - weil jeder Sekundärschlüssel auch die PK-Spalten enthält. (Dieser Hinweis ist InnoDB-spezifisch.)
+0

Hallo, Danke für die Antwort – berap

+0

Paar 'region_code_id', 'local_number' ist "einzigartig", aber ich habe die Tabelle 'number_comments', wo Kommentar durch 'numbers.id' – berap

+0

OK verbinden. Ich habe noch ein paar Sachen hinzugefügt. Fahren Sie mit dem Hinzufügen von INDEX (region_code_id, local_number) als beste Option fort. –

Verwandte Themen