Mysql
 sql >> база данни >  >> RDS >> Mysql

MySQL и NoSQL:Помогнете ми да избера правилния

Трябва да прочетете следното и да научите малко за предимствата на добре проектираната таблица innodb и как най-добре да използвате клъстерирани индекси - достъпно само с 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/

след това проектирайте вашата система нещо в съответствие със следния опростен пример:

Примерна схема (опростена)

Важните характеристики са, че таблиците използват механизма innodb и първичният ключ за таблицата с нишки вече не е единичен auto_incrementing ключ, а съставен клъстериран ключ, базиран на комбинация от forum_id и thread_id. напр.

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

Всеки ред на форума включва брояч, наречен next_thread_id (unsigned int), който се поддържа от тригер и се увеличава всеки път, когато се добави нишка към даден форум. Това също означава, че можем да съхраняваме 4 милиарда нишки на форум, вместо общо 4 милиарда нишки, ако използваме един първичен ключ auto_increment за 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

Недостатъкът на използването на съставен ключ е, че вече не можете просто да изберете нишка по стойност на един ключ, както следва:

select * from threads where thread_id = y;

трябва да направите:

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

Въпреки това, кодът на вашето приложение трябва да е наясно кой форум разглежда потребителят, така че не е точно трудно да се приложи - съхранявайте текущо разглеждания forum_id в променлива на сесията или скрито поле на формуляр и т.н....

Ето опростената схема:

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 ;

Може да сте забелязали, че съм включил reply_count като част от първичния ключ, което е малко странно, тъй като (forum_id, thread_id) композитът е уникален сам по себе си. Това е просто оптимизация на индекса, която спестява малко I/O, когато се изпълняват заявки, които използват reply_count. Моля, вижте 2-те връзки по-горе за повече информация относно това.

Примерни заявки

Все още зареждам данни в моите примерни таблици и досега имам заредени прибл. 500 милиона реда (наполовина колкото вашата система). Когато процесът на зареждане приключи, трябва да очаквам да имам приблизително:

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

Нарочно накарах някои от форумите да съдържат повече от 5 милиона теми, например, форум 65 има 15 милиона теми:

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

Изпълнение на заявка

select sum(next_thread_id) from forums;

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

под innodb сумирането на next_thread_ids за да даде общ брой нишки е много по-бързо от обикновено:

select count(*) from threads;

Колко теми има форум 65:

select next_thread_id from forums where forum_id = 65

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

отново това е по-бързо от обикновено:

select count(*) from threads where forum_id = 65

Добре, сега знаем, че имаме около 500 милиона теми досега, а форум 65 има 15 милиона теми - нека видим как се представя схемата :)

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

Изглежда ми доста ефективна - така че това е една таблица с 500+ милиона реда (и нарастваща) със заявка, която покрива 15 милиона реда за 0,02 секунди (докато е под товар!)

Допълнителни оптимизации

Те включват:

  • разделяне по диапазон

  • разделяне

  • хвърляне на пари и хардуер в него

и др...

надявам се да намерите този отговор за полезен :)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Кога да използвате STRAIGHT_JOIN с MySQL

  2. Създайте индекс на огромна таблица за производство на MySQL без заключване на таблицата

  3. Как да изберете всичко преди/след определен символ в MySQL – SUBSTRING_INDEX()

  4. MySQL репликация:Грешни транзакции в GTID базирана репликация

  5. MySQL - преброяване на общия брой редове в php