sql >> Database >  >> RDS >> Mysql

MySQL en NoSQL:help me de juiste te kiezen

Je zou het volgende moeten lezen en een beetje leren over de voordelen van een goed ontworpen innodb-tabel en hoe je geclusterde indexen het beste kunt gebruiken - alleen beschikbaar bij 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/

ontwerp vervolgens uw systeem in de trant van het volgende vereenvoudigde voorbeeld:

Voorbeeldschema (vereenvoudigd)

De belangrijke kenmerken zijn dat de tabellen de innodb-engine gebruiken en dat de primaire sleutel voor de threads-tabel niet langer een enkele auto_incrementing-sleutel is, maar een samengestelde geclusterde key gebaseerd op een combinatie van forum_id en thread_id. bijv.

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
...

Elke forumrij bevat een teller genaamd next_thread_id (unsigned int) die wordt onderhouden door een trigger en elke keer dat een thread wordt toegevoegd aan een bepaald forum wordt verhoogd. Dit betekent ook dat we 4 miljard threads per forum kunnen opslaan in plaats van in totaal 4 miljard threads als we een enkele auto_increment primaire sleutel voor thread_id gebruiken.

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

Het nadeel van het gebruik van een samengestelde sleutel is dat u een thread niet langer alleen kunt selecteren op basis van een enkele sleutelwaarde als volgt:

select * from threads where thread_id = y;

je moet doen:

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

Uw applicatiecode moet echter weten op welk forum een ​​gebruiker surft, dus het is niet bepaald moeilijk te implementeren - sla de momenteel bekeken forum_id op in een sessievariabele of verborgen formulierveld enz...

Hier is het vereenvoudigde schema:

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 ;

Je hebt misschien gemerkt dat ik reply_count als onderdeel van de primaire sleutel heb opgenomen, wat een beetje vreemd is omdat (forum_id, thread_id) composiet op zichzelf uniek is. Dit is slechts een indexoptimalisatie die wat I/O bespaart wanneer query's worden uitgevoerd die reply_count gebruiken. Raadpleeg de 2 links hierboven voor meer informatie hierover.

Voorbeeldvragen

Ik laad nog steeds gegevens in mijn voorbeeldtabellen en tot nu toe heb ik een geladen ca. 500 miljoen rijen (half zoveel als uw systeem). Wanneer het laadproces is voltooid, verwacht ik ongeveer:

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

Ik heb er bewust voor gezorgd dat sommige forums meer dan 5 miljoen threads bevatten, forum 65 heeft bijvoorbeeld 15 miljoen threads:

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

Runtimes voor query's

select sum(next_thread_id) from forums;

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

onder innodb is het optellen van de next_thread_ids om een ​​totaal aantal threads te geven veel sneller dan normaal:

select count(*) from threads;

Hoeveel threads heeft forum 65:

select next_thread_id from forums where forum_id = 65

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

nogmaals dit is sneller dan normaal:

select count(*) from threads where forum_id = 65

Ok nu weten we dat we tot nu toe ongeveer 500 miljoen threads hebben en forum 65 heeft 15 miljoen threads - laten we eens kijken hoe het schema presteert :)

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

Lijkt me behoorlijk performant - dus dat is een enkele tabel met 500+ miljoen rijen (en groeiend) met een query die 15 miljoen rijen beslaat in 0,02 seconden (onder belasting!)

Verdere optimalisaties

Deze omvatten:

  • partitioneren op bereik

  • scherven

  • er geld en hardware tegenaan gooien

enz...

hoop dat je dit antwoord nuttig vindt :)



  1. Hoe een externe sleutelbeperking te maken met ON UPDATE CASCADE in SQL Server - SQL Server / TSQL-zelfstudie, deel 79

  2. SQL Server Parallel Back-up Herstellen -1

  3. Oracle Instant Client installeren

  4. MySql gebruiken met Entity Framework 4 en de Code-First Development CTP