← Назад к вопросам

С какими СУБД работал

1.8 Middle🔥 171 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Опыт работы с различными СУБД

Транскрипция: СУБД = Система Управления Базами Данных (DBMS — Database Management System). В своей карьере я работал с несколькими типами СУБД: реляционными, документными и в памяти. Каждая имеет свои особенности и применение.

1. PostgreSQL (реляционная)

Это моя основная СУБД для большинства проектов. PostgreSQL — это мощная, open-source база с отличной поддержкой JSON и расширениями.

@Configuration
public class PostgresConfig {
    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:postgresql://localhost:5432/myapp");
        config.setUsername("postgres");
        config.setPassword("password");
        config.setMaximumPoolSize(20); // Connection pooling
        config.setMinimumIdle(5);
        config.setConnectionTimeout(10000);
        return new HikariDataSource(config);
    }
}

// Пример сложного запроса с JSON
@Entity
@Table(name = "users")
public class User {
    @Id
    private UUID id;
    
    @Column(name = "settings", columnDefinition = "jsonb")
    private Map<String, Object> settings; // Хранимся как JSON
    
    @Column(name = "created_at", columnDefinition = "TIMESTAMP WITH TIME ZONE")
    private LocalDateTime createdAt;
}

// Запрос: найти пользователей с конкретным settings параметром
String query = "SELECT * FROM users WHERE settings->>'theme' = ?";
// PostgreSQL может искать в JSON напрямую!

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

  • Полнотекстовый поиск (FTS)
  • JSON/JSONB типы
  • Arrays, UUID нативно
  • Полная ACID поддержка
  • Отличная документация

Когда использую:

  • Основное приложение, главная БД
  • Сложные запросы с JOIN'ами
  • Нужна 100% надёжность (банки, платежи)

2. MySQL (реляционная)

Часто встречается в legacy проектах и компаниях, выбравших его раньше.

@Configuration
public class MySQLConfig {
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/myapp?serverTimezone=UTC&useSSL=false");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        return dataSource;
    }
}

// MySQL требует explicit типы для дат
@Entity
@Table(name = "orders")
public class Order {
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_at")
    private Date createdAt;
    
    // В PostgreSQL можно просто LocalDateTime
}

Отличия от PostgreSQL:

  • Проще в настройке для начинающих
  • Медленнее на сложных запросах
  • Нет встроенного JSON
  • MyISAM (старый) не поддерживает транзакции

Когда использую:

  • Наследие, когда уже есть MySQL
  • Простые CRUD операции
  • Когда нужна максимальная совместимость с хостингом

3. MongoDB (документная NoSQL)

Документная БД, где каждый документ может иметь свою структуру.

@Configuration
public class MongoConfig {
    @Bean
    public MongoClient mongoClient() {
        return MongoClients.create("mongodb://localhost:27017");
    }
}

// Документ может быть полностью разным
@Document(collection = "users")
public class User {
    @Id
    private String id; // MongoDB автогенерирует ObjectId
    
    private String email;
    private String name;
    
    // Опциональные поля — просто добавляем
    private List<Address> addresses;
    private Map<String, Object> metadata;
}

@Service
public class UserMongoService {
    @Autowired
    private MongoTemplate mongoTemplate;
    
    public List<User> findUsersByCity(String city) {
        // MongoDB позволяет searchить по nested полям
        Query query = new Query(
            Criteria.where("addresses.city").is(city)
        );
        return mongoTemplate.find(query, User.class);
    }
}

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

  • Гибкая схема (Schema-less)
  • Горизонтальная масштабируемость (Sharding)
  • Быстро писать новый код
  • Агрегация данных (Aggregation Pipeline)

Когда использую:

  • Неструктурированные данные (logs, events)
  • Нужна горизонтальная масштабируемость
  • Быстрый прототип
  • Analytics, где данные постоянно меняются

4. Redis (in-memory)

Редис — это не реляционная БД, а хранилище ключ-значение в памяти. Используется для кэша, сессий, очередей.

@Configuration
public class RedisConfig {
    @Bean
    public LettuceConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory();
    }
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        return template;
    }
}

@Service
public class CacheService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    // Кэш с TTL
    public void cacheUserProfile(UUID userId, UserProfile profile) {
        String key = "user:profile:" + userId;
        redisTemplate.opsForValue().set(key, profile, 1, TimeUnit.HOURS);
    }
    
    // Получение из кэша
    public UserProfile getUserProfile(UUID userId) {
        String key = "user:profile:" + userId;
        return (UserProfile) redisTemplate.opsForValue().get(key);
    }
    
    // Redis для очередей (например, отправка emails)
    public void pushEmailJob(String email, String subject) {
        redisTemplate.opsForList().rightPush("email_queue", 
            new EmailJob(email, subject));
    }
    
    public EmailJob popEmailJob() {
        return (EmailJob) redisTemplate.opsForList().leftPop("email_queue");
    }
    
    // Redis для счётчиков (rate limiting)
    public boolean isRateLimited(String userId, int maxRequests, long windowSeconds) {
        String key = "rate_limit:" + userId;
        Long count = redisTemplate.opsForValue().increment(key);
        
        if (count == 1) {
            redisTemplate.expire(key, windowSeconds, TimeUnit.SECONDS);
        }
        
        return count > maxRequests;
    }
}

Когда использую Redis:

  • Кэширование (вспомогательное хранилище)
  • Сессии пользователей
  • Очереди задач (Message Queue)
  • Rate limiting
  • Real-time счётчики
  • Pub/Sub (broadcast сообщений)

5. Elasticsearch (поисковая)

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

@Configuration
public class ElasticsearchConfig {
    @Bean
    public RestHighLevelClient client() {
        return new RestHighLevelClient(
            RestClient.builder(new HttpHost("localhost", 9200))
        );
    }
}

@Service
public class ArticleSearchService {
    @Autowired
    private RestHighLevelClient elasticsearchClient;
    
    // Индексирование статьи
    public void indexArticle(Article article) throws IOException {
        IndexRequest request = new IndexRequest("articles");
        request.id(article.getId().toString());
        request.source(
            "title", article.getTitle(),
            "content", article.getContent(),
            "author", article.getAuthor(),
            "created_at", article.getCreatedAt()
        );
        
        elasticsearchClient.index(request, RequestOptions.DEFAULT);
    }
    
    // Полнотекстовый поиск
    public List<Article> searchArticles(String query) throws IOException {
        SearchRequest searchRequest = new SearchRequest("articles");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        
        sourceBuilder.query(
            QueryBuilders.multiMatchQuery(query, "title", "content")
                .fuzziness(Fuzziness.AUTO) // Поддержка опечаток
        );
        
        searchRequest.source(sourceBuilder);
        SearchResponse response = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
        
        return Arrays.stream(response.getHits().getHits())
            .map(hit -> parseArticle(hit.getSourceAsMap()))
            .collect(Collectors.toList());
    }
}

Когда использую Elasticsearch:

  • Полнотекстовый поиск
  • Большие объёмы логов (ELK stack)
  • Analytics данные
  • Когда PostgreSQL FTS недостаточно

6. Cassandra (распределённая)

В одном проекте нужна была горизонтальная масштабируемость для времённых рядов (time-series data).

@Configuration
public class CassandraConfig {
    @Bean
    public CqlSession session() {
        return CqlSession.builder()
            .addContactPoint(new InetSocketAddress("localhost", 9042))
            .withLocalDatacenter("datacenter1")
            .build();
    }
}

@Table(value = "events")
public class Event {
    @PrimaryKey
    private EventKey key;
    
    @Column
    private String eventType;
    
    @Column
    private Map<String, String> metadata;
}

// Cassandra отлично подходит для логов и метрик
@Service
public class EventLogService {
    @Autowired
    private CqlSession session;
    
    public void logEvent(UUID userId, String eventType, Map<String, String> metadata) {
        // Быстрое добавление событий (очень высокий throughput)
        String query = "INSERT INTO events (user_id, timestamp, event_type, metadata) VALUES (?, ?, ?, ?)";
        session.execute(
            SimpleStatement.builder(query)
                .addPositionalValue(userId)
                .addPositionalValue(Instant.now())
                .addPositionalValue(eventType)
                .addPositionalValue(metadata)
                .build()
        );
    }
}

Когда использую Cassandra:

  • Время-ряды (time-series)
  • Очень высокий throughput (миллионы событий в секунду)
  • Распределённая архитектура
  • НЕ нужны ACID транзакции

Выбор СУБД: сравнение

СУБДИспользованиеМасштабируемостьACIDСкорость
PostgreSQLОсновная БДВертикальнаяДаСредняя
MySQLLegacy, простоеВертикальнаяДа (InnoDB)Средняя
MongoDBDocs, flexibleГоризонтальнаяPartialБыстро
RedisКэш, сессииГоризонтальнаяНетОчень быстро
ElasticsearchFull-text searchГоризонтальнаяНетБыстро
CassandraTime-seriesГоризонтальнаяНетОчень быстро

Мой подход к выбору СУБД

  1. По умолчанию PostgreSQL — универсален и надёжен
  2. Если нужна масштабируемость → MongoDB или Cassandra
  3. Если нужен кэш → Redis
  4. Если нужна полнотекстовый поиск → Elasticsearch
  5. Если legacy → работаю с тем, что есть

Основное правило: выбирай инструмент под конкретную задачу, не наоборот.