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

Какие бы спроектировал индексы для поиска сотрудников, принятых в течение недели по заданному условию

2.0 Middle🔥 121 комментариев
#Базы данных и SQL

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

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

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

Какие бы спроектировал индексы для поиска сотрудников, принятых в течение недели

Таблица сотрудников

CREATE TABLE employees (
    id BIGINT PRIMARY KEY,
    name VARCHAR(255),
    email VARCHAR(255) UNIQUE,
    department VARCHAR(100),
    position VARCHAR(100),
    hire_date DATE,
    status VARCHAR(50),
    salary DECIMAL(10,2),
    is_active BOOLEAN
);

1. Базовый поиск по дате найма

SELECT * FROM employees 
WHERE hire_date BETWEEN CURRENT_DATE - 7 AND CURRENT_DATE
ORDER BY hire_date DESC;

CREATE INDEX idx_hire_date ON employees(hire_date DESC);

2. Поиск по отделу и дате найма

SELECT * FROM employees 
WHERE department = IT 
  AND hire_date >= CURRENT_DATE - 7
  AND is_active = true
ORDER BY hire_date DESC;

CREATE INDEX idx_dept_hire_date_active ON employees(
    department,           -- Фильтр по отделению
    hire_date DESC,       -- Range и сортировка
    is_active            -- Фильтр
);

3. Covering Index (оптимизация)

CREATE INDEX idx_employees_covering ON employees(
    department,
    hire_date DESC
) INCLUDE (
    id, name, email, position, salary
);

-- Index-only scan (без доступа к таблице)

4. Full Text поиск по имени

CREATE INDEX idx_name_fulltext ON employees USING GIN(
    to_tsvector(english, name)
);

5. Рекомендуемая стратегия

-- Основной индекс
CREATE INDEX idx_hire_date ON employees(hire_date DESC);

-- Составной индекс
CREATE INDEX idx_dept_hire_date ON employees(
    department, hire_date DESC
) INCLUDE (name, email, position);

-- По статусу
CREATE INDEX idx_status_hire_date ON employees(
    is_active, hire_date DESC
);

-- Unique на email
CREATE UNIQUE INDEX idx_email ON employees(email);

-- Full text
CREATE INDEX idx_name_fulltext ON employees 
USING GIN(to_tsvector(english, name));

6. Leftmost Prefix Rule

Для индекса (department, position, hire_date):

-- Использует индекс
WHERE department = IT AND position = Manager;

-- Использует индекс (partial)
WHERE department = IT;

-- НЕ использует индекс (пропущен first column)
WHERE position = Manager;

7. Spring Data JPA

@Entity
@Table(indexes = {
    @Index(name = "idx_hire_date", columnList = "hire_date DESC"),
    @Index(name = "idx_dept_hire", columnList = "department, hire_date DESC"),
    @Index(name = "idx_email", columnList = "email", unique = true)
})
public class Employee {
    @Id private Long id;
    @Column(unique = true) private String email;
    private String name;
    private String department;
    private LocalDate hireDate;
    private boolean isActive;
}

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    List<Employee> findByDepartmentAndHireDateBetweenOrderByHireDateDesc(
        String department, LocalDate start, LocalDate end);
}

Проверка индексов

EXPLAIN ANALYZE
SELECT * FROM employees 
WHERE department = IT
  AND hire_date >= CURRENT_DATE - 7
ORDER BY hire_date DESC;

-- Хорошо: "Index Scan" или "Index Only Scan"
-- Плохо: "Seq Scan" (без индекса)

Когда НЕ индексировать

❌ Избегай:

  • Булевы столбцы (low selectivity)
  • Часто обновляемые столбцы
  • BLOB/TEXT поля (используй Full Text)
  • Столбцы с 30%+ NULL

✅ Индексируй:

  • WHERE фильтры
  • JOIN условия
  • ORDER BY столбцы
  • Уникальные значения