Mysql
 sql >> Baza danych >  >> RDS >> Mysql

MySQL i NoSQL:pomóż mi wybrać właściwy

Powinieneś przeczytać poniższe i dowiedzieć się trochę o zaletach dobrze zaprojektowanej tabeli innodb oraz o tym, jak najlepiej używać indeksów klastrowych - dostępne tylko w innodb!

http://dev.mysql.com/doc /refman/5.0/en/innodb-index-types.html

http://www. xaprb.com/blog/2006/07/04/how-to-exploit-mysql-index-optimizations/

następnie zaprojektuj swój system zgodnie z następującym uproszczonym przykładem:

Przykładowy schemat (uproszczony)

Ważną cechą jest to, że tabele korzystają z mechanizmu innodb, a klucz podstawowy dla tabeli wątków nie jest już pojedynczym kluczem auto_inkrementacji, ale złożonym klastrowym klucz oparty na kombinacji forum_id i thread_id. np.

threads - primary key (forum_id, thread_id)

forum_id    thread_id
========    =========
1                   1
1                   2
1                   3
1                 ...
1             2058300  
2                   1
2                   2
2                   3
2                  ...
2              2352141
...

Każdy wiersz forum zawiera licznik o nazwie next_thread_id (unsigned int), który jest utrzymywany przez wyzwalacz i zwiększa się za każdym razem, gdy wątek zostanie dodany do danego forum. Oznacza to również, że możemy przechowywać 4 miliardy wątków na forum, a nie łącznie 4 miliardy wątków, jeśli użyjemy pojedynczego klucza podstawowego auto_increment dla thread_id.

forum_id    title   next_thread_id
========    =====   ==============
1          forum 1        2058300
2          forum 2        2352141
3          forum 3        2482805
4          forum 4        3740957
...
64        forum 64       3243097
65        forum 65      15000000 -- ooh a big one
66        forum 66       5038900
67        forum 67       4449764
...
247      forum 247            0 -- still loading data for half the forums !
248      forum 248            0
249      forum 249            0
250      forum 250            0

Wadą korzystania z klucza złożonego jest to, że nie można już wybrać wątku za pomocą pojedynczej wartości klucza w następujący sposób:

select * from threads where thread_id = y;

musisz zrobić:

select * from threads where forum_id = x and thread_id = y;

Jednak kod aplikacji powinien być świadomy tego, które forum przegląda użytkownik, więc nie jest to trudne do zaimplementowania - zapisz aktualnie przeglądany forum_id w zmiennej sesji lub ukrytym polu formularza itp...

Oto uproszczony schemat:

drop table if exists forums;
create table forums
(
forum_id smallint unsigned not null auto_increment primary key,
title varchar(255) unique not null,
next_thread_id int unsigned not null default 0 -- count of threads in each forum
)engine=innodb;


drop table if exists threads;
create table threads
(
forum_id smallint unsigned not null,
thread_id int unsigned not null default 0,
reply_count int unsigned not null default 0,
hash char(32) not null,
created_date datetime not null,
primary key (forum_id, thread_id, reply_count) -- composite clustered index
)engine=innodb;

delimiter #

create trigger threads_before_ins_trig before insert on threads
for each row
begin
declare v_id int unsigned default 0;

  select next_thread_id + 1 into v_id from forums where forum_id = new.forum_id;
  set new.thread_id = v_id;
  update forums set next_thread_id = v_id where forum_id = new.forum_id;
end#

delimiter ;

Być może zauważyłeś, że dołączyłem liczbę odpowiedzi jako część klucza podstawowego, co jest nieco dziwne, ponieważ kompozyt (forum_id, thread_id) jest unikalny sam w sobie. Jest to po prostu optymalizacja indeksu, która oszczędza część operacji we/wy podczas wykonywania zapytań używających liczby_odpowiedzi. Aby uzyskać więcej informacji na ten temat, zapoznaj się z 2 linkami powyżej.

Przykładowe zapytania

Wciąż ładuję dane do moich przykładowych tabel i do tej pory mam załadowane ok. 500 milionów wierszy (o połowę mniej niż Twój system). Po zakończeniu procesu ładowania powinienem spodziewać się około:

250 forums * 5 million threads = 1250 000 000 (1.2 billion rows)

Celowo stworzyłem niektóre fora zawierające ponad 5 milionów wątków, na przykład forum 65 ma 15 milionów wątków:

forum_id    title   next_thread_id
========    =====   ==============
65        forum 65      15000000 -- ooh a big one

Czasy wykonywania zapytań

select sum(next_thread_id) from forums;

sum(next_thread_id)
===================
539,155,433 (500 million threads so far and still growing...)

pod innodb sumowanie next_thread_ids w celu uzyskania całkowitej liczby wątków jest znacznie szybsze niż zwykle:

select count(*) from threads;

Ile wątków ma forum 65:

select next_thread_id from forums where forum_id = 65

next_thread_id
==============
15,000,000 (15 million)

znowu jest to szybsze niż zwykle:

select count(*) from threads where forum_id = 65

Ok, teraz wiemy, że mamy do tej pory około 500 milionów wątków, a forum 65 ma 15 milionów wątków - zobaczmy, jak działa schemat :)

select forum_id, thread_id from threads where forum_id = 65 and reply_count > 64 order by thread_id desc limit 32;

runtime = 0.022 secs

select forum_id, thread_id from threads where forum_id = 65 and reply_count > 1 order by thread_id desc limit 10000, 100;

runtime = 0.027 secs

Wygląda na całkiem wydajną - więc jest to pojedyncza tabela z ponad 500 milionami wierszy (i rosnącymi) z zapytaniem, które obejmuje 15 milionów wierszy w 0,02 sekundy (podczas obciążenia!)

Dalsze optymalizacje

Należą do nich:

  • partycjonowanie według zakresu

  • fragmentowanie

  • rzucając w to pieniądze i sprzęt

itp...

mam nadzieję, że ta odpowiedź okaże się pomocna :)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Zapytanie SQL, aby uzyskać wartości kolumn, które odpowiadają wartości MAX innej kolumny?

  2. Jak przeprowadzić migrację samodzielnego Moodle do skalowalnej konfiguracji klastrowej bazy danych

  3. Łańcuch zamówienia SQL jako liczba

  4. Dynamicznie ładuj dane na div scroll za pomocą php, mysql, jquery i ajax

  5. Jak przechowywać powtarzające się daty, pamiętając o czasie letnim?