Разрабатывая какой-либо проект рано или поздно мы можем столкнуться с проблемой нагрузки на БД. Данных может быть очень много, а мы как-то должны выдерживать нагрузки, и должны быть готовы к её росту. В своём докладе я поделюсь опытом масштабирования БД, расскажу всё максимально подробно — с какими проблемами можно столкнуться, какие стратегии и подходы лучше всего заложить в проекте.
Проблемы:
— Много строк в таблицах.
— «Медленные» запросы.
Варианты масштабирование БД
— Секционирование / партицирование данных.
— Шардинг.
— Репликация.
Покажу на примерах и расскажу про готовые к использованию утилиты и инструменты.
15. CREATE TABLE news (
id bigint not null,
category_id int not null,
author character varying not null,
rate int not null,
title character varying
)
01.
02.
03.
04.
05.
06.
07.
15
26. CREATE RULE news_insert_to_ 1 AS ON INSERT TO news
WHERE ( category_id = 1 )
DO INSTEAD INSERT INTO news_1 VALUES (NEW.*)
CREATE RULE news_insert_to_ 2 AS ON INSERT TO news
WHERE ( category_id = 2 )
DO INSTEAD INSERT INTO news_2 VALUES (NEW.*)
01.
02.
03.
04.
05.
06.
07.
26
29. SELECT * FROM news
id category_id title author rate
1 1 Моя новость #1 Ivan 1
2 2 Моя новость #2 Oleg 1
3 3 Моя новость #3 Petr 1
29
30. SELECT * FROM news WHERE category_id = 1
id category_id title author rate
1 1 Моя новость #1 Ivan 1
SELECT * FROM news WHERE category_id IN (2, 3)
id category_id title author rate
2 2 Моя новость #2 Oleg 1
3 3 Моя новость #3 Petr 1
30
31. SELECT * FROM news_1
id category_id title author rate
1 1 Моя новость #1 Ivan 1
SELECT * FROM news_2
id category_id title author rate
2 2 Моя новость #2 Oleg 1
31
32. SELECT * FROM news_3
ERROR: relation "news_3" does not exist
SELECT * FROM ONLY news
id category_id title author rate
3 3 Моя новость #3 Petr 1
32
36. SELECT * FROM news WHERE category_id = 1 LIMIT 1
id category_id title author rate
1 1 Моя новость #1 Ivan 1
SELECT * FROM news_1 LIMIT 1
id category_id title author rate
1 1 Моя новость #1 Ivan 1
36
42. CREATE TABLE news (
id bigint not null,
category_id int not null,
author character varying not null,
rate int not null,
title character varying
)
01.
02.
03.
04.
05.
06.
07.
42
45. SELECT * FROM news WHERE category_id = 1
id category_id title author rate
1 1 Моя новость #1 Ivan 1
5 1 Моя новость #5 Ivan 1
SELECT * FROM news_1
id category_id title author rate
1 1 Моя новость #1 Ivan 1
5 1 Моя новость #5 Ivan 1
45
50. CREATE TABLE news (
id bigint not null,
category_id int not null
CONSTRAINT category_id_check CHECK (category_id = 1 ),
author character varying not null,
rate int not null,
title character varying
);
01.
02.
03.
04.
05.
06.
07.
08.
50
52. CREATE EXTENSION postgres_fdw;
CREATE SERVER news_1_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host ' 127.0.0.1 ', port ' 5432 ', dbname ' news_1 ');
CREATE USER MAPPING FOR postgres
SERVER news_1_server
OPTIONS (user ' postgres ', password ' postgres ');
01.
02.
03.
04.
05.
06.
07.
08.
09.
52
53. CREATE FOREIGN TABLE news_1 (
id bigint not null,
category_id int not null,
author character varying not null,
rate int not null,
title character varying
)
SERVER news_1_server
OPTIONS (schema_name ' public ', table_name ' news ')
01.
02.
03.
04.
05.
06.
07.
08.
09.
53
54. CREATE VIEW news AS
SELECT * FROM news_1
UNION ALL
SELECT * FROM news_2
01.
02.
03.
04.
54
55. CREATE RULE news_insert AS ON INSERT TO news
DO INSTEAD NOTHING;
CREATE RULE news_update AS ON UPDATE TO news
DO INSTEAD NOTHING;
CREATE RULE news_delete AS ON DELETE TO news
DO INSTEAD NOTHING;
01.
02.
03.
04.
05.
06.
07.
08.
55
56. CREATE RULE news_insert_to_1 AS ON INSERT TO news
WHERE ( category_id = 1 )
DO INSTEAD INSERT INTO news_1 VALUES (NEW.*);
CREATE RULE news_insert_to_2 AS ON INSERT TO news
WHERE ( category_id = 2 )
DO INSTEAD INSERT INTO news_2 VALUES (NEW.*);
01.
02.
03.
04.
05.
06.
07.
56