Переход на 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 за один день.

Поделитесь с другими:

Представления-классы
(Class-Based Views)

Детальное описание и структура классов Django.

Исправление ошибок, Django 2.1.8

Выпущена новая версия Django 2.1.8, в которой исправлена ошибка в админке, допущенная в версии 2.1.7: запрещено редактировать inline-элементы для ManyToManyField, если у пользователя есть только разрешение на просмотр.

Аутентификация в Django: полный пример входа, выхода и смены пароля

В этом руководстве вы узнаете, как легко добавить полноценную систему аутентификации приложение Django с функциями входа в систему, выхода из системы, смены пароля и сброса.

Django 2.2 предварительный выпуск 1

Выпущен релиз-кандидат 1 версии Django 2.2, в котором вы можете предварительно протестировать некоторые новые возможности перед выпуском Django 2.2.

Поиск узких мест производительности проекта на Django

При оптимизации производительности веб-приложения распространенная ошибка — начинать с оптимизации самой медленной страницы (или API). Помимо учета времени отклика, мы также должны учитывать трафик, который он получает, чтобы определить порядок оптимизации. В этой статье мы расскажем о веб-приложении Django, найдем узкие места с высокой эффективностью, а затем приступим к их оптимизации для повышения производительности.

Просмотр SQL запросов Django

Django ORM позволяет легко взаимодействовать с базой данных. Чтобы понять, что происходит за кулисами или увидеть производительность SQL, мы можем записать все запросы SQL, которые выполняются. В этой статье мы увидим различные способы достижения этого.

Как подключить виджет выбора даты в Django

Из этого руководства вы узнаете как легко подключить виджет выбора даты в своем проекте Django. Мы узнаем, как установить его вручную, потом как настроить пользовательский виджет и, наконец, как использовать стороннее приложение Django с поддержкой средств выбора даты и времени.

Исправление ошибок, Django 2.0.13

Сегодня был осуществлен новый выпуск исправлений Django 2.0.13. Исправлен сбой в django.utils.numberformat.format_number(), когда число имеет более 200 цифр (#30177).

Новый формат middleware в Django 2

MIddleware (промежуточный слой) используются для модификации объекта приходящего запроса в представление (view) или для модификации объекта ответа, возвращаемого из представления. Они позволяют нам изменять запросы/ответы глобально.

Массовое обновление записей в Django используя аннотации и подзапросы

Как массово обновлять записи в Django с помощью аннотаций и подзапросов.

Структура шаблонов в Django

Существует два основных способа организации структуры шаблонов Django: на уровне приложений и пользовательский, на уровне проекта, который указывается в setting.py.