Переход на PostgreSQL с MySQL в Django
В этой статье можно узнать о шагах, которые нужно предпринять, чтобы перенести проекты Django с MySQL на PostgreSQL.
База данных MySQL — хорошее начало для маленьких и средних проектов. Она известен и широко используется, имеет хорошую документацию. Также есть отличные клиенты для простого управления, такие как phpMyAdmin (web), HeidiSQL (Windows) или Sequel Pro (macOS).
Когда кто-то начинает задумываться о масштабировании проекта, то нужно выбирать что-то более подходящее. Это должна быть БД, которая быстрая, надежная и поддерживает стандарты ANSI для реляционных баз данных. То, что использует большинство разработчиков Django. И такой базой данных для большинства профессионалов является PostgreSQL. PostgreSQL позволяет использовать несколько специфичных функций от разработчиков, которые не доступны в MySQL, например многомерные массивы, поля JSON, поля пары ключ-значение, специальные нечувствительные к регистру текстовые поля, поля диапазонов, специальные индексы, нормальный полнотекстовый поиск и т.п. Для новичка, который хочет быстро влиться в разработку с использованием PostgreSQL, лучший клиент БД — pgAdmin (macOS, linux, windows ). Он может показаться слишком сложным сначала (по сравнению с клиентами MySQL), но поскольку в Django есть встроенная админка и удобный ORM, не будет частой необходимостью проверять базу данных в ее "родном" формате.
Итак, что нужно для перехода от MySQL к PostgreSQL? Это можно сделать за несколько шагов, с использованием pgloader, чтобы помочь в миграции данных.
1. Подготовка MySQL базы
Негобходимо убедиться, что все миграции проведены:
(env)$ python manage.py migrate --settings=settings.production
Теперь можно сделать копию БД и перейти к миграции данных.
2. Установка pgloader
Установить pgloader можно используя средства дистрибутива или скачать из репозитория и собрать из исходных текстов.
3. Создание пользователя и базы в PostgreSQL
В отличие от MySQL, создание новых пользователей и баз данных PostgreSQL обычно происходит в оболочке, а не в клиенте базы данных.
Создадим пользователя и базу данных с таким же именем myproject.
$ createuser --createdb --password myproject
$ createdb --username=myproject myproject
4. Создание схемы
Свяжите проект с базой данных PostgreSQL в настройках, например:
DATABASES = {
'postgresql': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': get_secret("DATABASE_NAME"), 'USER': get_secret("DATABASE_USER"),
'PASSWORD': get_secret("DATABASE_PASSWORD"),
},
}
DATABASES['default'] = DATABASES['postgresql']
В этом функция get_secret () возвращает конфиденциальную информацию из переменных окружения или текстового файла, который не отслеживается при управлении версиями. Но можно использовать любой свой предпочитаемый метод.
Запуск миграции для создания таблиц и связей в новой базе PostgreSQL:
(env)$ python manage.py migrate --settings=settings.local
5. Создание сценария переноса данных
Pgloader использует конфигурационные файлы с настройками, определяющими, как проводить с миграции. Создаем файл конфигурации myproject.load со следующим содержимым:
LOAD DATABASE
FROM mysql://mysql_username:mysql_password@localhost/mysql_dbname
INTO postgresql:///myproject
WITH truncate, data only, disable triggers, preserve index names, include no drop, reset sequences
ALTER SCHEMA 'mysql_dbname' RENAME TO 'public' ;
6. Запуск миграции данных
$ pgloader myproject.load
Как правило, вылезет большое количество предупреждений о преобразованиях типов. Обычно это можно проигнорировать, потому что сценарий будет стараться угадывать, как конвертировать данные при импорте. Если происходят ошибки, связанные с дублированием данных или таблиц с внешними ключами с потерянными записями, необходимо исправить проблемы в базе данных MySQL, а затем повторить этот процесс. Для этого нужно очистить базу данных MySQL, обновить локальную копию, заново создать базу данных PostgreSQL с помощью команд dropdb и createdb, запустить Django-миграции, чтобы создать схему базы данных, и снова скопировать данные.
7. Адаптация кода
Когда база данных будет успешно перенесена, необходимо запустить тесты проекта Django и исправить все проблемы, связанные с PostgreSQL. Код, написанный с использованием Django ORM, будет работать без проблем. Скорее всего возникнут проблемы с сырым SQL, методом extra()
QuerySet и преобразованиями типов.
Как правило, это примерно такие различия:
- Строковые значения в запросах PostgreSQL всегда оборачиваются 'одиночными кавычками'.
- PostgreSQL не конвертирует типы при сравнении значений автоматически, как это делает MySQL. Если используется какой-либо сырой SQL-код, нужно выполнить преобразование перед сравнением, например
CAST(blog_post.id AS text) = likes_like.object_id
илиblog_post.id::text = likes_like.object_id
. Последний синтаксис с двумя двоеточиями не понимат MySQL, поэтому, если нужно поддерживать обе базы данных, нужно для каждой версии БД свой код. - PostgreSQL чувствителен к регистру для сравнения строк, поэтому в фильтрах QuerySet нужно будет использовать
*__iexact
поиск вместо*__ exact
и*__icontains
вместо*__contains
. - При сортировке преобразовывать столбец в нижний регистр с помощью функции
Lower ()
:from django.db import models posts = Post.objects.order_by(models.Lower('title'))
-
При использовании
*__in
убедиться, что тип перечисленных элементов соответствует типу поля модели. Например, может быть модельLike
с общим отношением, то естьcontent_type
иobject_id
, которые вместе создают общий внешний ключ с любым экземпляром модели. Полеobject_id
обычно имеет тип строки, но идентификаторы связанных моделей могут быть целыми числами, строками илиUUID
. Если нужно получить понравившиеся сообщения, первичным ключам которых являются целые числа, нужно преобразовать значенияobject_id
в целые числа, прежде чем назначать их для поискаpk__in
в фильтре:liked_ids = map( int, Like.objects.filter( user=request.user, content_type=ContentType.objects.get_for_model(Post) ).values("object_id", flat=True) ) liked_posts = Post.objects.filter(pk__in=liked_ids)
8. Повторить процесс на "боевом" сервере
После удачной локальной миграции можно приступать к миграции рабочего проекта.
Вывод
PostgreSQL имеет больше ограничений по работе с ним, чем MySQL, но обеспечивает большую производительность, большую стабильность и лучшее соответствие стандартам. Кроме того, в PostgreSQL существует множество функций, недоступных в MySQL. Если повезет, то можно перевести проект с MySQL на PostgreSQL за один день.
Вернуться на верх