ETL Pipeline: SQLite to PostgreSQL
Наш фундамент (схема базы данных в PostgreSQL) успешно заложен. Я изучил предоставленную тобой базу данных dicechess.db. Оказалось, что данные лежат в таблице games, а сами ходы упакованы в колонку moves_json. Всего в таблице ровно 141,703 партии. Формат JSON полностью совпадает с тем, что я видел ранее.
Это отличные новости! Нам не нужно возиться с 140 000 отдельных файлов. Читать из SQLite гораздо удобнее и быстрее.
User Review Required
Ниже представлен обновленный план. Если он выглядит логично, мы приступим к написанию и запуску скрипта импорта.
Описание исходных данных
В таблице games (SQLite) есть:
- Метаданные:
game_id,white_player_username,black_player_username,tournament_id,result,allow_doubling,start_time,bet,time_limit,time_bonus,white_player_rating,black_player_rating. - Вспомогательные данные:
metadata_json - Основные ходы:
moves_json
Формат moves_json внутри выглядит так:
{
"gameMoveHistoryStateMap": {
"0": { "fen": "...", "dices": [], "gameMoveHistoryMove": null },
"1": { "fen": "...", "dices": [...], "gameMoveHistoryMove": null },
"2": { "fen": "...", "dices": [...], "gameMoveHistoryMove": {"from": "E2", "to": "E4"} }
}
}Proposed Changes
Мы создадим Python скрипт src/importer.py, который будет подключаться одновременно к двум базам (SQLite на чтение, PostgreSQL на запись).
1. Парсинг FEN (DFEN)
Из каждого состояния мы берем поле fen.
Мы разделяем его по пробелам, чтобы получить normalized_fen (первые 4 группы: расположение фигур, цвет, рокировка, битое поле).
parts = fen.split(" ")
normalized_fen = " ".join(parts[0:4])Затем мы считаем хэш: xxhash.xxh64(normalized_fen).intdigest().
2. Сборка микро-ходов в Turn
Поскольку в JSON записан каждый микро-ход (состояние до хода, после первого, после второго), скрипт должен объединять их в единый логический ход (Turn).
- Начало хода: Цвет активного игрока не меняется, кубики брошены (
dicesне пустой). Мы фиксируемposition_idи значение кубиков. - Микро-ходы: Мы собираем
gameMoveHistoryMove(например,E2E4,G1F3) в списокplayed_moves. - События: Если в
moves_jsonмы видим изменение поляbank(ставка), мы генерируемGameEventудвоения. - Конец хода: Цвет активного игрока меняется или ходы закончились. Ход закрывается и сохраняется.
3. Кэширование позиций и пакетная вставка (Batching)
Позиций будут миллионы. Чтобы импорт не занял неделю:
- Скрипт будет держать в памяти локальный
dictхэшей позиций. - Мы будем читать партии из SQLite блоками по 1000 штук.
- Для каждой 1000 партий мы будем использовать массовую вставку (
INSERT ... ON CONFLICT DO NOTHING) в PostgreSQL. - Мы будем использовать библиотеку
tqdmдля красивого прогресс-бара, чтобы ты видел, с какой скоростью переливаются твои 140 тысяч партий.
Verification Plan
Automated Tests
- Перед запуском на всей базе мы прогоним импорт на первых 10 партиях (
LIMIT 10) и убедимся, что они корректно разложились по таблицамplayers,games,turns,positionsв PostgreSQL.
Manual Verification
- После завершения импорта мы проверим
SELECT COUNT(*) FROM games;в PostgreSQL (должно быть 141,703). - Выполним сложный аналитический запрос, чтобы убедиться, что структура работает идеально.