🗄 База данных¶
Supabase PostgreSQL 16 + TimescaleDB
20+ таблиц, RLS, ~400M записей MeterValues в год
20+Таблиц
400MЗаписей/год (MeterValues)
RLSRow Level Security
ER-диаграмма¶
erDiagram
users ||--o{ charging_sessions : "has"
users ||--o{ balance_transactions : "has"
users ||--o{ favorites : "has"
users ||--o{ push_subscriptions : "has"
users ||--o{ otp_codes : "verifies"
stations ||--o{ connectors : "has"
stations ||--o{ charging_sessions : "hosts"
stations }o--|| partners : "owned_by"
stations }o--|| locations : "located_at"
connectors ||--o{ charging_sessions : "used_in"
connectors ||--o{ bookings : "reserved"
charging_sessions ||--o{ meter_values : "generates"
charging_sessions ||--o{ charging_receipts : "produces"
partners ||--o{ partner_payouts : "receives"
partners }o--|| users : "is_user"
corporate_groups ||--o{ corporate_employees : "has"
corporate_groups ||--o{ corporate_limits : "sets"
corporate_employees }o--|| users : "is_user"
tariff_plans ||--o{ tariff_rules : "defines"
stations }o--|| tariff_plans : "uses"
ocpp_logs }o--|| stations : "from"
Таблицы¶
Core¶
| Таблица | Описание | Примерный объём |
|---|---|---|
| users | Пользователи (все роли) | ~100K записей |
| stations | Зарядные станции | 198 записей |
| connectors | Коннекторы станций | 396 записей |
| locations | Локации станций | ~100 записей |
Business¶
| Таблица | Описание | Примерный объём |
|---|---|---|
| charging_sessions | Зарядные сессии | ~1.8M/год |
| meter_values | Телеметрия (каждые 15 сек) | ~400M/год |
| balance_transactions | Пополнения и списания | ~500K/год |
| charging_receipts | PDF-чеки за зарядку | ~1.8M/год |
| bookings | Бронирования коннекторов | ~200K/год |
| favorites | Избранные станции пользователей | ~50K |
Partners¶
| Таблица | Описание | Примерный объём |
|---|---|---|
| partners | Владельцы станций | ~50 записей |
| partner_payouts | Выплаты партнёрам (80%) | ~600/год |
| tariff_plans | Тарифные планы | ~20 |
| tariff_rules | Правила тарифов (время, мощность) | ~100 |
Corporate¶
| Таблица | Описание | Примерный объём |
|---|---|---|
| corporate_groups | Корпоративные клиенты | ~50 |
| corporate_employees | Сотрудники компаний | ~500 |
| corporate_limits | Лимиты по сотрудникам | ~500 |
System¶
| Таблица | Описание | Примерный объём |
|---|---|---|
| otp_codes | SMS OTP коды (TTL 5 мин) | Ротация |
| push_subscriptions | VAPID push подписки | ~80K |
| ocpp_logs | Логи OCPP событий | ~50M/год |
| guest_sessions | Гостевые зарядки | ~200K/год |
Объём данных по фазам¶
| Фаза | Станций | MeterValues/мин | Записей/день | Записей/год |
|---|---|---|---|---|
| 1 | 5 | ~20 | ~29K | ~10M |
| 2 | 35 | ~140 | ~200K | ~73M |
| 3 | 78 | ~310 | ~450K | ~164M |
| 4 | 138 | ~550 | ~790K | ~290M |
| 5 | 178 | ~710 | ~1.0M | ~370M |
| 6 | 198 | ~800 | ~1.1M | ~400M |
Оптимизация¶
TimescaleDB для MeterValues¶
-- Гипертаблица для автоматического партиционирования
SELECT create_hypertable('meter_values', 'timestamp');
-- Политика сжатия (после 7 дней)
ALTER TABLE meter_values SET (
timescaledb.compress,
timescaledb.compress_orderby = 'timestamp DESC'
);
SELECT add_compression_policy('meter_values', INTERVAL '7 days');
-- Политика удаления (после 2 лет)
SELECT add_retention_policy('meter_values', INTERVAL '2 years');
Индексы¶
-- Основные индексы
CREATE INDEX idx_sessions_user ON charging_sessions(user_id, created_at DESC);
CREATE INDEX idx_sessions_station ON charging_sessions(station_id, status);
CREATE INDEX idx_meter_session ON meter_values(session_id, timestamp DESC);
CREATE INDEX idx_stations_status ON stations(status, partner_id);
CREATE INDEX idx_balance_user ON balance_transactions(user_id, created_at DESC);
Row Level Security (RLS)¶
-- Партнёр видит только свои станции
CREATE POLICY partner_stations ON stations
FOR SELECT USING (partner_id = auth.uid());
-- Клиент видит только свои сессии
CREATE POLICY user_sessions ON charging_sessions
FOR SELECT USING (user_id = auth.uid());