.NET Разработчик
6.52K subscribers
442 photos
3 videos
14 files
2.12K links
Дневник сертифицированного .NET разработчика. Заметки, советы, новости из мира .NET и C#.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 1397. #БазыДанных
Сегодня порекомендую видео про нормализацию базы данных. 1я, 2я, 3я, 4я и даже 5я нормальные формы. Автор на простых примерах объясняет, что это такое, почему это важно и как позволяет избежать несогласованности данных.

Приятного изучения https://youtu.be/GFQaEYEc8_8

Извините, видео на английском, но можно включить автоматически переведённые субтитры.
👍10
День 2095. #ЗаметкиНаПолях #БазыДанных
Типы Ключей

В реляционной БД ключи гарантируют, что любая запись в таблице может быть однозначно идентифицирована одним полем или комбинацией полей в таблице. Ключи также связывают таблицы БД и определяют отношения между ними.

Первичные ключи
Первичный ключ — это поле, которое однозначно идентифицирует каждую запись в таблице в реляционной БД. Они делятся на 2 группы:
- Естественные - существующие данные, например, серия и номер паспорта человека, VIN-номер машины, ISBN книги и т.п.
- Суррогатные (синтетические) - сгенерированы специально для использования в БД и не имеют представления среди реальных атрибутов сущности. Нередко используется автоинкрементное поле для автоматического назначения уникального номера каждой записи в таблице.

См. также «Вы Пожалеете, что Использовали Естественные Ключи»

Внешние ключи
Внешний ключ позволяет связать две таблицы, устанавливая связь между полем одной таблицы и полем первичного ключа другой таблицы.
Например, БД библиотеки может состоять из 3 таблиц — книги, клиенты и выданные книги. Внешние ключи могут быть введены для связи таблицы выданных книг с таблицами книг и клиентов.

Столбец идентификатора клиента может существовать:
- в таблице клиентов как первичный ключ
- в таблице выданных книг как внешний ключ
Столбец идентификатора книги может существовать:
- в таблице книг как первичный ключ
- в таблице выданных книг как внешний ключ

Необходимо соблюдать особую осторожность при вставке и удалении данных из столбца внешнего ключа. Неосторожное удаление или вставка может разрушить связь между двумя таблицами. Чтобы избежать этого, в большинстве СУБД есть правила ограничений:
- вставка - запрет вставки записи со значением внешнего ключа, которое отсутствует как значение первичного ключа в связанной таблице;
- обновление – если существуют связанные записи с таким значением внешнего ключа: запрет обновления, каскадное обновление связанных записей или установка значений ключа в NULL у связанных записей (поле должно допускать NULL);
- удаление - если существуют связанные записи с таким значением внешнего ключа: запрет удаления, каскадное удаление связанных записей или установка значений ключа в NULL у связанных записей (поле должно допускать NULL).

Составной (composite) ключ
Это особый тип первичного ключа, который использует содержимое двух или более полей из таблицы для создания уникального значения. Например, номер паспорта не является уникальным, уникальной является комбинация двух полей: серия паспорта и номер паспорта.

Комбинированный (compound) ключ
Комбинированный ключ похож на составной ключ в том, что для создания уникального значения требуются два или более полей. Однако комбинированный ключ создаётся, когда два или более первичных ключа из разных таблиц присутствуют как внешние ключи внутри сущности. Внешние ключи используются вместе для уникальной идентификации каждой записи.

Комбинированные ключи всегда состоят из двух или более первичных ключей из других таблиц. В своих таблицах оба этих ключа уникально идентифицируют данные, но в таблице, использующей комбинированный ключ, они оба необходимы для уникальной идентификации данных.

Например, первичным ключом в таблице «товары в заказе» может быть комбинированный ключ, состоящий из идентификатора заказа и идентификатора товара.

Источник: https://www.bbc.co.uk/bitesize/guides/z4wf8xs/revision/4
👍16
День 2408. #Архитектура #БазыДанных
Postgres Слишком Хорош. Начало

Разные инди-разработчики и основатели стартапов лихорадочно собирают технологические стеки с Redis для кэширования, RabbitMQ для очередей, Elasticsearch для поиска и MongoDB, потому что… так надо? Оказывается, есть слон в комнате, которого никто не хочет замечать: Postgres может буквально всё это. И он делает это лучше, чем вы думаете.

Миф о том, что Postgres не масштабируется
Часто говорят, что Postgres — это «всего лишь РСУБД», и для решения специализированных задач нужны специализированные инструменты. Но Instagram масштабируется до 14 миллионов пользователей на одном экземпляре Postgres. Discord обрабатывает миллиарды сообщений. Notion построил весь свой продукт на Postgres. Только они не используют Postgres так, будто на дворе 2005 год.

1. Системы Очередей
В Postgres есть нативная поддержка LISTEN/NOTIFY, и он может обрабатывать очереди заданий лучше, чем многие специализированные решения:
-- Простая очередь на Postgres
CREATE TABLE job_queue (
id SERIAL PRIMARY KEY,
job_type VARCHAR(50),
payload JSONB,
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT NOW(),
processed_at TIMESTAMP
);

-- ACID-совместимая обработка заданий
BEGIN;
UPDATE job_queue
SET status = 'processing', processed_at = NOW()
WHERE id = (
SELECT id FROM job_queue
WHERE status = 'pending'
ORDER BY created_at
FOR UPDATE SKIP LOCKED
LIMIT 1
)
RETURNING *;
COMMIT;

Это обеспечивает обработку «ровно один раз» без дополнительной инфраструктуры.

2. Хранилище Ключ-значение
В Postgres есть JSONB, который выполняет большую часть того, что вам нужно:
-- Альтернатива Redis
CREATE TABLE kv_store (
key VARCHAR(255) PRIMARY KEY,
value JSONB,
expires_at TIMESTAMP
);

-- GIN индекс для запросов к JSON
CREATE INDEX idx_kv_value ON kv_store USING GIN (value);

SELECT * FROM kv_store
WHERE value @> '{"user_id": 12345}';

Оператор @> - секретное оружие Postgres'а. Он быстрее большинства запросов NoSQL, и ваши данные остаются согласованными.

3. Полнотекстовый поиск
Кластеры Elasticsearch дороги и сложны. В Postgres есть встроенный полнотекстовый поиск, который поразительно хорош:
-- Добавляем поиск к любой таблице
ALTER TABLE posts ADD COLUMN search_vector tsvector;

-- Авто-обновляемый индекс поиска
CREATE OR REPLACE FUNCTION update_search_vector()
RETURNS trigger AS $$
BEGIN
NEW.search_vector := to_tsvector('english',
COALESCE(NEW.title, '') || ' ' ||
COALESCE(NEW.content, '')
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Ранжированные результаты поиска
SELECT title, ts_rank(search_vector, query) as rank
FROM posts, to_tsquery('startup & postgres') query
WHERE search_vector @@ query
ORDER BY rank DESC;

Это позволяет без проблем обрабатывать нечёткое соответствие, стемминг и ранжирование по релевантности.

4. Функции Реального Времени
Postgres LISTEN/NOTIFY обеспечивает обновления в реальном времени без дополнительных сервисов:
-- Уведомления клиентов об изменениях
CREATE OR REPLACE FUNCTION notify_changes()
RETURNS trigger AS $$
BEGIN
PERFORM pg_notify('table_changes',
json_build_object(
'table', TG_TABLE_NAME,
'action', TG_OP,
'data', row_to_json(NEW)
)::text
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Ваше приложение отслеживает эти уведомления и отправляет обновления пользователям.

Окончание следует…

Источник:
https://dev.to/shayy/postgres-is-too-good-and-why-thats-actually-a-problem-4imc
👍48
День 2409. #Архитектура #БазыДанных
Postgres Слишком Хорош. Окончание

Начало

Скрытая стоимость «специализированных» инструментов
Помимо собственно платы за каждый специализированный сервис, есть много скрытых расходов на них.

Операционные расходы
- Мониторинг, обновления и отладка разных сервисов;
- Разные шаблоны масштабирования и режимы сбоев;
- Необходимость поддержки нескольких конфигураций;
- Раздельные процедуры резервного копирования и аварийного восстановления;
- Разные аспекты безопасности для каждого сервиса.

Сложности разработки
- Разные клиентские библиотеки и шаблоны подключения;
- Координация развёртываний нескольких сервисов;
- Несогласованность данных между системами;
- Сложные сценарии тестирования;
- Разные подходы к настройке производительности.
Если вы размещаете сервер самостоятельно, добавьте управление сервером, исправления безопасности и неизбежные сеансы отладки, когда Redis решает израсходовать всю вашу память, и т.п. Postgres делает всё это в одном сервисе, которым вы уже управляете.

Единая масштабируемая БД
Большинство людей не осознаёт, что один экземпляр Postgres может справиться с огромными объёмами данных. Речь идёт о миллионах транзакций в день, терабайтах данных и тысячах одновременных подключений. Вся магия кроется в архитектуре Postgres. Она невероятно хорошо масштабируется вертикально, а когда вам наконец понадобится горизонтальное масштабирование, у вас есть проверенные решения, такие как:
- Реплики чтения для масштабирования запросов;
- Партиционирование для больших таблиц;
- Организация пулов подключений для конкурентности;
- Логическая репликация для распределённых конфигураций.
Большинство компаний никогда до этого не доходят. Вас, вероятно, устроит один экземпляр, пока вы не начнёте обслуживать миллионы пользователей или сложные аналитические задачи. Сравните это с управлением отдельными сервисами, каждый из которых масштабируется по-разному.

Остановите оверинжиниринг с первого дня
Главная ловушка современной разработки — архитектурная астронавтика. Мы проектируем системы для задач, которых у нас нет, с трафиком, которого мы никогда не видели, для масштаба, которого, возможно, никогда не достигнем.

Начните с простого, с Postgres. Отслеживайте реальные узкие места, а не воображаемые. Масштабируйте конкретные компоненты, когда достигаете реальных ограничений. Добавляйте сложность только тогда, когда это решает реальные проблемы. Пользователям не важна ваша архитектура. Им важно, работает ли ваш продукт и решает ли он их проблемы.

Postgres может быть вашей основной БД, кэшем, очередью, поисковой системой и системой реального времени одновременно. И всё это с поддержкой ACID-транзакций во всех областях:
-- Одна транзакция, несколько операций
BEGIN;
INSERT INTO users (email) VALUES ('user@example.com');
INSERT INTO job_queue (job_type, payload)
VALUES ('send_welcome_email', '{"user_id": 123}');
UPDATE kv_store SET value = '{"last_signup": "2024-01-15"}'
WHERE key = 'stats';
COMMIT;


Итого
Postgres может быть слишком хорош сам по себе. Он настолько мощен, что делает большинство других сервисов ненужными для 90% приложений. Индустрия убедила нас, что нам нужны специализированные инструменты для всего, но, возможно, мы просто усложняем задачу.
Ваш стартап не должен быть витриной распределённых систем. Он должен решать реальные проблемы для реальных людей. Postgres позволяет вам сосредоточиться на этом. Поэтому в следующий раз, когда кто-то предложит добавить Redis «для производительности» или MongoDB «для гибкости», спросите: «Вы попробовали сначала сделать это в Postgres?»

Источник: https://dev.to/shayy/postgres-is-too-good-and-why-thats-actually-a-problem-4imc
👍23