sql >> Database teknologi >  >> RDS >> Mysql

MySQL og NoSQL:Hjælp mig med at vælge den rigtige

Du bør læse følgende og lære lidt om fordelene ved en veldesignet innodb-tabel, og hvordan du bedst bruger klyngede indekser - kun tilgængelig med innodb!

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

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

design derefter dit system noget i stil med følgende forenklede eksempel:

Eksempelskema (forenklet)

De vigtige funktioner er, at tabellerne bruger innodb-motoren, og den primære nøgle til trådtabellen er ikke længere en enkelt auto_incrementing-nøgle, men en sammensat clustered nøgle baseret på en kombination af forum_id og thread_id. f.eks.

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

Hver forumrække indeholder en tæller kaldet next_thread_id (usigneret int), som vedligeholdes af en trigger og trinviser hver gang en tråd tilføjes til et givet forum. Dette betyder også, at vi kan gemme 4 milliarder tråde pr. forum i stedet for 4 milliarder tråde i alt, hvis vi bruger en enkelt auto_increment primærnøgle til 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

Ulempen ved at bruge en sammensat nøgle er, at du ikke længere bare kan vælge en tråd med en enkelt nøgleværdi som følger:

select * from threads where thread_id = y;

du skal gøre:

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

Din applikationskode bør dog være opmærksom på, hvilket forum en bruger gennemser, så det er ikke ligefrem svært at implementere - gem det aktuelt viste forum_id i en sessionsvariabel eller skjult formularfelt osv...

Her er det forenklede skema:

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 ;

Du har måske bemærket, at jeg har inkluderet reply_count som en del af den primære nøgle, hvilket er lidt mærkeligt, da (forum_id, thread_id) sammensat er unikt i sig selv. Dette er blot en indeksoptimering, som gemmer noget I/O, når forespørgsler, der bruger reply_count, udføres. Se venligst de 2 links ovenfor for yderligere information om dette.

Eksempler på forespørgsler

Jeg indlæser stadig data i mine eksempeltabeller og indtil videre har jeg indlæst ca. 500 millioner rækker (halvt så mange som dit system). Når indlæsningsprocessen er færdig, skulle jeg forvente at have ca.:

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

Jeg har bevidst fået nogle af foraerne til at indeholde mere end 5 millioner tråde, for eksempel har forum 65 15 millioner tråde:

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

Forespørgselskørselstider

select sum(next_thread_id) from forums;

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

under innodb summering er next_thread_ids for at give et samlet antal tråde meget hurtigere end det sædvanlige:

select count(*) from threads;

Hvor mange tråde har forum 65:

select next_thread_id from forums where forum_id = 65

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

igen dette er hurtigere end det sædvanlige:

select count(*) from threads where forum_id = 65

Ok nu ved vi, at vi har omkring 500 millioner tråde indtil videre, og forum 65 har 15 millioner tråde - lad os se, hvordan skemaet klarer sig :)

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

Det ser ret effektiv ud for mig - så det er en enkelt tabel med 500+ millioner rækker (og voksende) med en forespørgsel, der dækker 15 millioner rækker på 0,02 sekunder (mens den er under belastning!)

Yderligere optimeringer

Disse vil omfatte:

  • partitionering efter område

  • skæring

  • smider penge og hardware efter det

osv...

håber du finder dette svar nyttigt :)



  1. En oversigt over PRINT-erklæringen i SQL Server

  2. Sådan får du gårsdagens dato i MySQL

  3. Lagring af filer i SQL-database ved hjælp af FILESTREAM – Del 1

  4. Sådan opretter du indlejret tabel som databaseobjekt i Oracle