sql >> Databáze >  >> RDS >> Mysql

MySQL a NoSQL:Pomozte mi vybrat ten správný

Měli byste si přečíst následující a dozvědět se něco málo o výhodách dobře navržené tabulky innodb ao tom, jak nejlépe používat seskupené indexy – dostupné pouze s 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/

pak navrhněte svůj systém něco ve smyslu následujícího zjednodušeného příkladu:

Ukázkové schéma (zjednodušené)

Důležité je, že tabulky používají modul innodb a primární klíč pro tabulku vláken již není jediný auto_incrementing klíč, ale složený shlukovaný klíč založený na kombinaci forum_id a thread_id. např.

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ždý řádek fóra obsahuje počítadlo nazvané next_thread_id (unsigned int), které je udržováno spouštěčem a zvyšuje se pokaždé, když je vlákno přidáno do daného fóra. To také znamená, že můžeme uložit 4 miliardy vláken na fórum namísto 4 miliard vláken celkem, pokud použijeme jediný primární klíč auto_increment pro 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

Nevýhodou použití složeného klíče je, že již nemůžete pouze vybrat vlákno podle jedné hodnoty klíče následovně:

select * from threads where thread_id = y;

musíte udělat:

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

Kód vaší aplikace by si však měl být vědom toho, které fórum uživatel prohlíží, takže implementace není zrovna obtížná – uložte aktuálně zobrazené forum_id do proměnné relace nebo skrytého pole formuláře atd...

Zde je zjednodušené schéma:

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 ;

Možná jste si všimli, že jsem zahrnul reply_count jako součást primárního klíče, což je trochu zvláštní, protože kompozit (forum_id, thread_id) je jedinečný sám o sobě. Toto je pouze optimalizace indexu, která šetří některé I/O při provádění dotazů, které používají response_count. Další informace o tom naleznete na 2 výše uvedených odkazech.

Příkladové dotazy

Stále načítám data do svých ukázkových tabulek a zatím mám načteno cca. 500 milionů řádků (polovina více než váš systém). Po dokončení procesu načítání bych měl očekávat přibližně:

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

Záměrně jsem vytvořil, že některá fóra obsahují více než 5 milionů vláken, například fórum 65 má 15 milionů vláken:

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

Běhové časy dotazů

select sum(next_thread_id) from forums;

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

pod innodb je sčítání next_thread_ids k získání celkového počtu vláken mnohem rychlejší než obvykle:

select count(*) from threads;

Kolik vláken má fórum 65:

select next_thread_id from forums where forum_id = 65

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

opět je to rychlejší než obvykle:

select count(*) from threads where forum_id = 65

Dobře, teď víme, že máme zatím asi 500 milionů vláken a fórum 65 má 15 milionů vláken - podívejme se, jak si schéma vede :)

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

Zdá se mi docela výkonný - takže to je jedna tabulka s více než 500 miliony řádků (a stále rostoucí) s dotazem, který pokrývá 15 milionů řádků za 0,02 sekundy (při zatížení!)

Další optimalizace

Patří mezi ně:

  • rozdělení podle rozsahu

  • sharding

  • házet do toho peníze a hardware

atd...

doufám, že vám tato odpověď pomůže :)



  1. Více plánů pro identický dotaz

  2. SQL Server - najít n-tý výskyt v řetězci

  3. SQL Server:dynamické pivotování přes 5 sloupců

  4. Rozdíl v měsících mezi daty v MySQL