2010-11-11 14 views
6

Jest to prawdopodobnie typowa sytuacja, ale nie mogłem znaleźć konkretnej odpowiedzi na SO lub Google.Utrzymywanie dużej tabeli unikalnych wartości w MySQL

Mam dużą tabelę (> 10 milionów wierszy) relacji przyjacielskich na bazie danych MySQL, która jest bardzo ważna i musi być utrzymana w taki sposób, aby nie było duplikatów. W tabeli przechowywane są identyfikatory użytkowników. SQL dla tabeli jest:

CREATE TABLE possiblefriends(
id INT NOT NULL AUTO_INCREMENT, 
PRIMARY KEY(id), 
user INT, 
possiblefriend INT) 

Sposób tabela działa to, że każdy użytkownik ma około 1000 lub tak „potencjalnych przyjaciół”, które są odkryte i muszą być przechowywane, ale duplikat „ewentualne przyjaciele” muszą być unikany.

Problem polega na tym, że ze względu na konstrukcję programu w ciągu jednego dnia muszę dodać 1 milion wierszy lub więcej do tabeli, która może być lub nie być powtórzonymi wpisami wiersza. Wydaje się, że prosta odpowiedź polega na sprawdzeniu każdego wiersza, aby sprawdzić, czy jest on duplikatem, a jeśli nie, wstaw go do tabeli. Jednak ta technika będzie prawdopodobnie bardzo powolna, ponieważ rozmiar tabeli zwiększy się do 100 milionów wierszy, 1 miliarda wierszy lub więcej (co spodziewam się wkrótce).

Jaki jest najlepszy (tj. Najszybszy) sposób na utrzymanie tego unikalnego stołu?

Nie muszę mieć tabeli z unikalnymi wartościami zawsze pod ręką. Potrzebuję go raz dziennie do zadań wsadowych. W takim przypadku, czy powinienem utworzyć oddzielną tabelę, która wstawia wszystkie możliwe wiersze (zawierające duplikaty wierszy i wszystkie), a następnie na koniec dnia, utworzyć drugą tabelę, która oblicza wszystkie unikalne wiersze w pierwszej tabeli?

Jeśli nie, jaki jest najlepszy sposób dla tej tabeli długoterminowej?

(Jeśli indeksy są najlepszym rozwiązaniem długoterminowym, proszę mi powiedzieć, który indeksy do użycia)

+0

pytanie, czy u potrzebę zapytania do tabeli 'possiblefriends'? Po prostu myślę, że prawdopodobnie możesz podzielić tabelę według użytkownika, to przyniesie korzyści, gdy zapytasz, ale może się okazać, że w dłuższej perspektywie przerodzi się w katastrofę konserwacyjną – ajreal

+0

@ajreal: czy masz na myśli, że każdy użytkownik ma swój własny stół? byłoby około miliona użytkowników, więc to prawdopodobnie bardzo skomplikowałoby sprawę. – eric

+0

tak, to wspomniałem, że może to doprowadzić do katastrofy konserwacyjnej, a co powiesz na użycie 1k użytkownika na stolik? wyobraź sobie, że umieściłeś wszystkie dane w jednym stole, a dzieje się tak, że stół się zawiesił i nie można go odzyskać, a nawet można go odzyskać, jak długo możesz wytrzymać z czasem przestoju? – ajreal

Odpowiedz

7

Dodaj unikatowy indeks na (user, possiblefriend) następnie użyć jednego z:

to pl upewnij się, że nie otrzymujesz błędów podczas próby wstawienia duplikatu wiersza.

Możesz również rozważyć, czy możesz upuścić automatycznie zwiększający się klucz podstawowy i użyć (user, possiblefriend) jako klucza podstawowego. Spowoduje to zmniejszenie rozmiaru twojej tabeli, a także klucz podstawowy będzie działał jako indeks, co pozwoli ci uniknąć konieczności tworzenia dodatkowego indeksu.

Zobacz także:

+1

Czytałem to pytanie. Czy INSERT IGNORE lub INSERT ... NA DUPLICATE KEY UPDATE wydajne dla tabeli z 100s z milionów wierszy w ogóle? – eric

+1

@eric: Wyobrażam sobie, że 'INSERT IGNORE' jest najszybszy, ale po prostu zgaduję. Aby mieć pewność, że można przeprowadzić test wydajności na wszystkich trzech metodach. Najwyżej głosowana odpowiedź na pytanie, które połączyłem, zaleca użycie 'INSERT ... ON DUPLICATE KEY UPDATE'. –

+1

NB - musi to być unikalny indeks! – symcbean

2

unikatowy indeks pozwoli mieć pewność, że pole jest rzeczywiście wyjątkowy, można dodać indeks unikatowy tak:

CREATE TABLE possiblefriends( 
id INT NOT NULL AUTO_INCREMENT, 
PRIMARY KEY(id), 
user INT, 
possiblefriend INT, 
PRIMARY KEY (id), 
UNIQUE INDEX DefUserID_UNIQUE (user ASC, possiblefriend ASC)) 

To również znacznie zwiększy dostęp do twojego stołu.

Twój inny problem z masowym wkładki jest trochę bardziej skomplikowane, można użyć wbudowany ON duplikat KEY UPDATE poniżej funkcji:

INSERT INTO table (a,b,c) VALUES (1,2,3) 
    ON DUPLICATE KEY UPDATE c=c+1; 

UPDATE table SET c=c+1 WHERE a=1; 
+0

dzięki. czy zawsze lepiej jest używać indeksu? Czy nie byłoby żadnych kosztów korzystania z indeksu dla większych tabel, które powinienem rozważyć? – eric

Powiązane problemy