Масштабирование базы данных через шардирование и...

62
Масштабирование базы данных через шардирование и партиционирование Иванов Денис 2gis.ru

Upload: 2-

Post on 25-Jul-2015

152 views

Category:

Technology


10 download

TRANSCRIPT

Page 1: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Масштабирование базы данныхчерез шардирование ипартиционированиеИванов Денис

2gis.ru

Page 2: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

2GIS WebAPI

Page 3: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Данные

•  8 стран

•  250 городов

•  50 тыс населенных пунктов

•  5 млн организаций

•  50 млн гео-объектов

И еще много всего

3

Page 4: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Нагрузка

•  25 млн. пользователей в месяц

•  2000 RPS

•  3 датацентра

4

Page 5: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Много данных

Page 6: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Долгие запросы

Page 7: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Масштабирование БД как решениепроблемы

•  Шардинг

•  Вертикальный

•  Горизонтальный

•  Репликация

7

Page 8: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Партицирование(вертикальный шардинг)

Page 9: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС
Page 10: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Горизонтальный шардинг

Page 11: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС
Page 12: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Репликация

Page 13: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС
Page 14: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

1. Партицирование

Page 15: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 16: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

CREATE TABLE news_1 (

) INHERITS (news)

01.

02.

16

Page 17: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Наследованная таблица•  Будет:

•  Все колонки от родителя

•  "Свои" колонки

•  Не будет:

•  Ограничений (Constraint)

•  Индексов (Index)

•  Триггеров (Trigger)

17

Page 18: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

CREATE TABLE news_1 (

CHECK ( category_id = 1 )

) INHERITS (news)

01.

02.

03.

18

Page 19: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Строгое значение

CHECK ( author = 'Denis' )

Список значений

CHECK ( author IN ('Denis', 'Anton', 'Oleg') )

Диапазон значений

CHECK ( rate > 100 AND rate <= 200 )

19

Page 20: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

CREATE TABLE news_rate_100_200 (

CHECK ( rate BETWEEN 100 AND 200 )

) INHERITS (news)

CREATE TABLE news_rate_200_300 (

CHECK ( rate BETWEEN 200 AND 300 )

) INHERITS (news)

01.

02.

03.

04.

05.

06.

07.

20

Page 21: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

CREATE TABLE news_rate_100_200 (

CHECK ( rate > 100 AND rate <= 200 )

) INHERITS (news)

CREATE TABLE news_rate_201_300 (

CHECK ( rate > 200 AND rate <= 300 )

) INHERITS (news)

01.

02.

03.

04.

05.

06.

07.

21

Page 22: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

CREATE TABLE news_1 (

CHECK ( category_id = 1 )

) INHERITS (news)

CREATE TABLE news_rate_100 (

CHECK ( rate = 100 )

) INHERITS (news)

01.

02.

03.

04.

05.

06.

07.

22

Page 23: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

CREATE TABLE news_1 (

CHECK ( category_id = 1 )

) INHERITS ( news )

01.

02.

03.

23

Page 24: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

CREATE RULE news_insert_to_ 1 AS ON INSERT TO news

WHERE ( category_id = 1 )

DO INSTEAD INSERT INTO news_1 VALUES (NEW.*)

01.

02.

03.

24

Page 25: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

CREATE TABLE news_1 (

CHECK ( category_id = 1 )

) INHERITS ( news )

CREATE TABLE news_2 (

CHECK ( category_id = 2 )

) INHERITS ( news )

01.

02.

03.

04.

05.

06.

07.

25

Page 26: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 27: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

INSERT INTO news

(id, category_id , title, author, rate)

VALUES

(1, 1 , 'Моя новость #1', 'Ivan', 1)

INSERT INTO news

(id, category_id , title, author, rate)

VALUES

(2, 2 , 'Моя новость #2', 'Oleg', 1)

01.

02.

03.

04.

01.

02.

03.

04.

27

Page 28: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

INSERT INTO news

(id, category_id , title, author, rate)

VALUES

(3, 3 , 'Моя новость #3', 'Petr', 1)

01.

02.

03.

04.

28

Page 29: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 30: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 31: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 32: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 33: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

INSERT INTO news_1

(id, category_id , title, author, rate)

VALUES

(4, 1 , 'Моя новость #4', 'Ivan', 1)

01.

02.

03.

04.

33

Page 34: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

INSERT INTO news_1

(id, category_id , title, author, rate)

VALUES

(4, 4 , 'Моя новость #4', 'Ivan', 1)

ERROR: new row for relation " news_1 " violates

check constraint " news_1_category_id_check "

01.

02.

03.

04.

01.

02.

34

Page 35: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

INSERT INTO news

(id, category_id , title, author, rate)

VALUES

(5, 1 , 'Моя новость #5', 'Ivan', 1),

(6, 2 , 'Моя новость #6', 'Oleg', 1),

(7, 3 , 'Моя новость #7', 'Petr', 1)

01.

02.

03.

04.

05.

06.

35

Page 36: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 37: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

EXPLAIN ANALYZE

SELECT * FROM news WHERE category_id = 1

...

-> Seq Scan on news ...

Filter: (category_id = 1)

-> Seq Scan on news_1 ...

Filter: (category_id = 1)

...

01.

02.

01.

02.

03.

04.

05.

06.

37

Page 38: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

EXPLAIN ANALYZE

SELECT * FROM news_1

...

Seq Scan on news_1

...

01.

02.

01.

02.

03.

38

Page 39: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Точно также:•  UPDATE

•  DELETE

39

Page 40: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

CREATE INDEX news_rate_idx ON news (rate)

CREATE INDEX news_1_rate_idx ON news_1 (rate)

CREATE INDEX news_2_rate_idx ON news_2 (rate)

40

Page 41: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

PartitionMagic

Page 42: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 43: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

_2gis_partition_magic(' news ', ' category_id ')

43

Page 44: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

INSERT INTO news

(id, category_id , title, author, rate)

VALUES

(1, 1 , 'Моя новость #1', 'Ivan', 1),

(2, 2 , 'Моя новость #2', 'Oleg', 1),

(3, 3 , 'Моя новость #3', 'Petr', 1),

(4, 1 , 'Моя новость #4', 'Ivan', 1),

(5, 1 , 'Моя новость #5', 'Ivan', 1),

(6, 2 , 'Моя новость #6', 'Oleg', 1),

(7, 3 , 'Моя новость #7', 'Petr', 1)

01.

02.

03.

04.

05.

06.

07.

08.

09.

10.

44

Page 45: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 46: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Преимущества:

•  Создание недостающих партиций при вставке

•  Актуальная структура таблиц:

•  Колонки

•  Индексы

•  Проверки

•  Триггеры

46

Page 47: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

https://github.com/2gis/partition_magic

Page 48: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

2. Горизонтальный шардинг

Page 49: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС
Page 50: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 51: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

CREATE INDEX news_category_id_idx ON news

USING btree( category_id );

01.

02.

51

Page 52: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 53: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 54: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

CREATE VIEW news AS

SELECT * FROM news_1

UNION ALL

SELECT * FROM news_2

01.

02.

03.

04.

54

Page 55: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 56: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

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

Page 57: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

INSERT INTO news

(id, category_id , title, author, rate)

VALUES

(1, 1 , 'Моя новость #1', 'Ivan', 1),

(2, 2 , 'Моя новость #2', 'Oleg', 1),

(3, 3 , 'Моя новость #3', 'Petr', 1),

(4, 1 , 'Моя новость #4', 'Ivan', 1),

(5, 1 , 'Моя новость #5', 'Ivan', 1),

(6, 2 , 'Моя новость #6', 'Oleg', 1),

(7, 3 , 'Моя новость #7', 'Petr', 1)

01.

02.

03.

04.

05.

06.

07.

08.

09.

10.

57

Page 58: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

SELECT * FROM news

id category_id title author rate

1 1 Моя новость #1 Ivan 1

4 1 Моя новость #4 Ivan 1

5 1 Моя новость #5 Ivan 1

2 2 Моя новость #2 Oleg 1

6 2 Моя новость #6 Oleg 1

58

Page 59: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

SELECT * FROM news WHERE category_id = 2

id category_id title author rate

2 2 Моя новость #2 Oleg 1

6 2 Моя новость #6 Oleg 1

SELECT * FROM news_2

id category_id title author rate

2 2 Моя новость #2 Oleg 1

6 2 Моя новость #6 Oleg 1

59

Page 60: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

EXPLAIN ANALYZE

SELECT * FROM news

...

-> Foreign Scan on news_1

-> Foreign Scan on news_2

...

01.

02.

01.

02.

03.

04.

60

Page 61: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Подведём итоги•  Партицирование

•  Просто

•  Один сервер

•  Прирост производительности в 3-4 раза

•  Горизонтальный шардинг

•  Немного сложнее партицирования

•  Разные сервера для разных шардов

61

Page 62: Масштабирование базы данных через шардирование и партиционирование — Денис Иванов, 2ГИС

Вопросы?

Иванов Денис

[email protected]

62