Баженова Анна
англ. structured query language — «язык структурированных запросов»
Данные хранятся в консистентном состоянии
Как это можно реализовать?
КРАЙНЕ сложна в реализации из-за распределенных транзакций и не только.
Проблема: в любой момент на сервер может упасть метеорит, мы не должны терять данные в такой ситуации
Решение: сделаем несколько серверов, каждый из которых будет хранить полную копию данных
Хотим:
2 вида репликации:
Одна синхронная реплика, остальные асинхронные. Если с мастером что-то случается, синхронная реплика заменяет его. Если что-то случается с синхронной репликой, одна из асинхронных занимает ее место.
Проблема: хотим, чтобы один запрос затрагивал как можно меньше шардов
Подключаемся:
┌{ notebook }
├
│
│
│
│
├
│
│
├
│
│
│
CREATE DATABASE notebook;
┌{ notebook }
├─┬{ notes }
│ ├
│ ├
│ ├
│ ├
├─┬{ users }
│ ├
│ ├
├─┬{ categories }
│ ├
│ ├
│ ├
CREATE TABLE notes (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
text TEXT NOT NULL,
owner_id INTEGER
);
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE categories (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
best_note_id INTEGER
);
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE categories (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
best_note_id INTEGER
);
┌{ notebook }
├─┬{ notes }
│ ├──{ id: Integer }
│ ├──{ name: String }
│ ├──{ text: String }
│ ├──{ owner_id: Integer }
├─┬{ users }
│ ├──{ id: Integer }
│ ├──{ name: String }
├─┬{ categories }
│ ├──{ id: Integer }
│ ├──{ name: String }
│ ├──{ best_note_id: Integer }
CHAR(4) | "abc " |
VARCHAR(4) | "abc" |
TEXT | "abcdef" |
SMALLINT | [-215, 215 - 1] |
INTEGER | [-231, 231 - 1] |
BIGINT | [-263, 263 - 1] |
REAL | [10-37, 1037] |
DOUBLE PRECISION | [10-307, 10308] |
NUMERIC [(p[,s])] |
DECIMAL [(p[,s])] |
1 <= p <= 1000, 0 <= s <= p
SMALLSERIAL | [1, 215 - 1] |
SERIAL | [1, 231 - 1] |
BIGSERIAL | [1, 263 - 1] |
CREATE TABLE users (
id SERIAL
);
CREATE SEQUENCE users_id_seq;
CREATE TABLE users (
id integer NOT NULL DEFAULT nextval('users_id_seq')
);
ALTER SEQUENCE users_id_seq OWNED BY users.id;
SELECT * FROM users_id_seq;
+------------+-----+-----------+
| last_value | ... | is_called |
+------------+-----+-----------+
| 1 | ... | f |
+------------+-----+-----------+
SELECT * FROM users_id_seq;
+------------+-----+-----------+
| last_value | ... | is_called |
+------------+-----+-----------+
| 1 | ... | f |
+------------+-----+-----------+
TRUE | FALSE |
't' | 'f' |
'true' | 'false' |
'y' | 'n' |
'yes' | 'no' |
'on' | 'off' |
'1' | '0' |
timestamp [without time zone] | 8 bytes |
timestamp with time zone | 8 bytes |
date | 4 bytes |
time [without time zone] | 8 bytes |
time with time zone | 12 bytes |
interval | 16 bytes |
timestamp | '2004-10-19 10:23:54' |
timestamp with time zone | '2004-10-19 10:23:54+02' |
date | '2018-04-03' |
time | '04:05:06.789' |
time with time zone | '04:05:06.789-3' |
interval | '1 12:59:10' |
'{ значение1 разделитель значение2 разделитель ... }'
integer[][] -> '{{1,2,3},{4,5,6},{7,8,9}}'
text[] -> '{"apple", "orange", "cheese"}'
'{ "bar": "baz", "number": 7, "active": false }'
CREATE TABLE notes (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
text VARCHAR(255)
);
ALTER TABLE notes ADD COLUMN owner_id INTEGER;
ALTER TABLE notes DROP COLUMN owner_id;
ALTER TABLE notes ALTER COLUMN text TYPE TEXT;
ALTER TABLE notes ALTER COLUMN text SET NOT NULL;
ALTER TABLE notes RENAME TO personal_notes;
DROP TABLE notes;
Механизм модификации структуры и данных в БД. Очень похоже на систему контроля версий. Если что-то пошло не так, то миграции можно откатить.
от англ. create, read, update, delete — «создать, прочесть, обновить, удалить»
INSERT INTO notes
(id, name, text)
VALUES
(1, 'Books', 'Books to read');
SELECT id, name AS title, text FROM notes;
+----+-------+---------------+
| id | title | text |
+----+-------+---------------+
| 1 | Books | Books to read |
+----+-------+---------------+
SELECT * FROM notes;
+----+-------+---------------+----------+
| id | name | text | owner_id |
+----+-------+---------------+----------+
| 1 | Books | Books to read | NULL |
+----+-------+---------------+----------+
SELECT * FROM notes_id_seq;
+------------+-----+-----------+
| last_value | ... | is_called |
+------------+-----+-----------+
| 1 | ... | f |
+------------+-----+-----------+
SELECT * FROM notes_id_seq;
+------------+-----+-----------+
| last_value | ... | is_called |
+------------+-----+-----------+
| 1 | ... | f |
+------------+-----+-----------+
INSERT INTO notes (name, text)
VALUES ('Films', 'Films to watch');
ERROR: duplicate key value violates
unique constraint "notes_pkey"
DETAIL: Key (id)=(1) already exists.
SELECT * FROM notes_id_seq;
+------------+-----+-----------+
| last_value | ... | is_called |
+------------+-----+-----------+
| 1 | ... | t |
+------------+-----+-----------+
INSERT INTO notes (name, text)
VALUES ('Films', 'Films to watch');
SELECT * FROM notes;
+----+-------+----------------+----------+
| id | name | text | owner_id |
+----+-------+----------------+----------+
| 1 | Books | Books to read | NULL |
| 2 | Films | Films to watch | NULL |
+----+-------+----------------+----------+
SELECT * FROM notes_id_seq;
+------------+-----+-----------+
| last_value | ... | is_called |
+------------+-----+-----------+
| 2 | ... | t |
+------------+-----+-----------+
SELECT id, name, text FROM notes
WHERE name = 'Films';
+----+-------+----------------+
| id | name | text |
+----+-------+----------------+
| 2 | Films | Films to watch |
+----+-------+----------------+
SELECT id, name AS title, text FROM notes
WHERE title = 'Films';
ERROR: column "title" does not exist
SELECT name FROM notes;
+----------+
| name |
+----------+
| Books |
| Films |
| Music |
| Rules |
| Markdown |
+----------+
SELECT name FROM notes
ORDER BY name DESC
OFFSET 2
LIMIT 2;
+----------+
| name |
+----------+
| Markdown |
| Films |
+----------+
SELECT count(*) FROM notes;
+-------+
| count |
+-------+
| 5 |
+-------+
SELECT name, owner_id
FROM notes;
+----------+----------+
| name | owner_id |
+----------+----------+
| Books | 3 |
| Films | 1 |
| Music | 2 |
| Rules | NULL |
| Markdown | 1 |
+----------+----------+
SELECT owner_id, count(*)
FROM notes
GROUP BY owner_id;
+----------+-------+
| owner_id | count |
+----------+-------+
| 1 | 2 |
| 2 | 1 |
| 3 | 1 |
| NULL | 1 |
+----------+-------+
+----------+----------+
| name | owner_id |
+----------+----------+
| Books | 3 |
| Films | 1 |
| Music | 2 |
| Rules | NULL |
| Markdown | 4 |
+----------+----------+
+------+--------+
| id | name |
+------+--------+
| 1 | Антон |
| 2 | Михаил |
| 3 | Олег |
| 4 | Андрей |
+------+--------+
SELECT n.name
FROM notes n
WHERE owner_id IN (
SELECT id
FROM users u
WHERE u.name LIKE 'А%'
);
+----------+
| name |
+----------+
| Films |
| Markdown |
+----------+
CREATE TABLE example_arrays
(numbers integer[]);
INSERT INTO example_arrays
(numbers)
VALUES ('{1,2,3}'),
('{4,5,6}');
SELECT numbers
FROM example_arrays;
+-----------+
| numbers |
+-----------+
| {1,2,3} |
| {4,5,6} |
+-----------+
SELECT numbers[2]
FROM example_arrays;
+-----------+
| numbers |
+-----------+
| 2 |
| 5 |
+-----------+
SELECT numbers[1:2]
FROM example_arrays;
+------------+
| numbers |
+------------+
| { 1, 2 } |
| { 4, 5 } |
+------------+
CREATE TABLE example_json
(info JSON);
INSERT INTO example_json
(info)
VALUES
('{"bar":"baz","number":7}'),
('{"bar":"foo","some":{"val":13}}');
SELECT info FROM example_json;
+-------------------------------+
| info |
+-------------------------------+
| {"bar":"baz","number":7} |
|{"bar":"foo","some":{"val":13}}|
+-------------------------------+
SELECT info->>'bar' AS bar
FROM example_json;
+-------+
| bar |
+-------+
| baz |
| foo |
+-------+
SELECT info->'some' AS some
FROM example_json
WHERE info->>'bar' = 'foo';
+--------------+
| some |
+--------------+
| {"value":13} |
+--------------+
UPDATE notes
SET text = 'My favorite books to read', owner_id = 4
WHERE id = 1;
DELETE FROM notes
WHERE id = 1;
BEGIN;
UPDATE users SET account = account - 10000
WHERE id = 3;
UPDATE users SET account = account + 10000
WHERE id = 4;
{ COMMIT | ROLLBACK };