メインコンテンツにスキップ
ブログデータベースDjango と SQL。データベースを拡張するためのダイナミックデュオ

Django と SQL。データベースを拡張するためのダイナミックデュオ

DjangoとSQLでデータベースを拡張する-ブログヘッダー

アプリケーションのニーズに合わせてデータベースをスケーリングし、最適化することは、重要な課題です。 Python と SQL データベースアプリケーションのために Django がどのように重労働をこなせるかについての私の最近のブログをまだ読んでいないなら、ぜひチェックしてみることをお勧めします。しかし、TL;DR バージョンは、SQL は SQL データベースに最適化されており、Python はそうではなく、Djangoは、この二つの言語を一緒に使うときに、摩擦や複雑さやコードを少なくして、より効果的なアプリケーションを作るのに役立つ素晴らしい仲介者だということです。

つまり、Django がデータベースアプリを作るという重い仕事をする一方で、データベースの日々の管理と監視はあなたが責任を持つことになるのです。これらの管理作業のいくつかは、Linode Managed Databases のようなサービスを使って、クラウドプロバイダに任せることができますが、スケールするにつれて、以下のような新しい障害を発見する可能性があります。

  • データベースマイグレーション。データベーススキームの変更を制御しながら、既存のデータベースを新しい目的の状態に変換すること。
  • マルチデータベースの展開。パフォーマンスを最適化するために、開発者はアプリケーションを設計し、分割された機能に対して別々のデータベースを使用することができます。たとえば、プライマリの読み取り/書き込み用データベースと、一般的なクエリ用の読み取り用レプリカデータベースを使用することができます。

もしあなたのデータベースの1つが SQL を使っているなら、Django を使って摩擦を減らし、かなりの量のデータを扱いながら、あなたの生活をとても楽にすることができます。

この 2 つの重要なデータベース管理のコンセプトの紹介は、Understanding Databasesebook と私の新しい教育用ビデオシリーズにある、実稼働可能な Django アプリケーションを構築するためのステップバイステップの説明と対をなしています。どちらの学習経路でも、 Django があなたのために SQL の重い仕事をするのを助けるでしょう。

データベースの移行
特に、データのニーズは時間の経過とともに変化するため、カラムのデータ型を正しく設定することは容易ではありません。例えば、タイトル欄の文字数を80文字にしたいとしたらどうでしょう?また、アイテムがいつデータベースに追加されたかを正確に追跡するために、タイムスタンプフィールドを追加する必要がある場合はどうでしょうか。

テーブルを作成した後に変更すると、いくつかの理由でかなり面倒なことになります。

  • 既存の価値観をどうするのか?
  • 新しいカラム/フィールドのデータが既存の行にない場合はどうすればよいですか?
  • カラムやフィールドを削除したらどうなりますか?データはどうなりますか?
  • 以前は存在しなかったリレーションを追加した場合はどうでしょうか(例:外部キー)。

Django の開発者にとって幸運なことに、私たちには makemigrationsmigrate.

実際にどのような仕組みになっているのか、見てみましょう。

以下は Django のデータモデルの例です。

class BlogArticle(models.Model):
    user = models.ForeignKey(User, default=1, on_delete=models.SET_DEFAULT)
    title = models.CharField(max_length=120)
    slug = models.SlugField(blank=True, null=True)
    content = models.TextField(blank=True, null=True)
    publish_timestamp = models.DateTimeField(
        auto_now_add=False,
        auto_now=False,
        blank=True,
        null=True,
    )

フィールドを追加してみましょう。

updated_by = models.ForeignKey(
        User, related_name="editor", null=True, blank=True, on_delete=models.SET_NULL
)

このフィールドにより、モデルに変更を加えた最後のユーザーを追跡することができます。 

モデルを更新してみよう。

class BlogArticle(models.Model):
    user = models.ForeignKey(User, default=1, on_delete=models.SET_DEFAULT)
    title = models.CharField(max_length=120)
    slug = models.SlugField(blank=True, null=True)
    content = models.TextField(blank=True, null=True)
    publish_timestamp = models.DateTimeField(
        auto_now_add=False,
        auto_now=False,
        blank=True,
        null=True,
    )
    # our new field
    updated_by = models.ForeignKey(
        User, related_name="editor", null=True, blank=True, on_delete=models.SET_NULL
    )

さて、このファイルを保存した後、この BlogArticle クラスは、(models.py)、この変更が発生したことをデータベースに知らせるにはどうしたらよいでしょうか。

方法は2つある。

  1. python manage.py makemigrations
  2. python manage.py migrate

この2つのコマンドが何をするのか、説明しましょう。

python manage.py makemigrations

python manage.py makemigrations の変化を探ります。 何れも models.py ファイルを Django プロジェクト全体で検索し、変更点を探します。もし変更が見つかれば、新しいpython ファイルが 変更案 SQLデータベースが ニーズ を作ることです。変更案は次のようなものです。

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('articles', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='article',
            name='updated_by',
            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='editor', to=settings.AUTH_USER_MODEL),
        ),
    ]

これはもちろん、単なるPython ファイルです。このファイルは、私たち (開発者) に、データベースで何が起こるべきかを教えてくれています。これは、結束を維持し、 Django ORM の組み込み機能を活用するために、SQL ではなくPython で書かれています。

しかし、なぜこれがあるべき姿のファイルなのでしょうか?まあ、いくつか理由があるんですけどね。

  • 起こるべきことが起こる前に見直す必要があれば、ここでキャッチすることができます。
  • この makemigrations コマンドではありません。 合わす この変更を確認するために、データベースを も起こる。
  • データベースは、これらの要件に合わせてすでに変更されている可能性があります(データベースを管理している人/ものに関連する多くの要因に依存します)。
  • もし、本番のデータベースを変更する前にテストを行う必要があるのなら、今がその絶好の機会だと思います。

この変更が(わかる範囲で)有効であると仮定して、変更をコミットすることができます。

python manage.py migrate

python manage.py migrate は私たちのためにデータベースを変更しようとします - すべてのフィールド、カラム、テーブル、外部キー、何でも構いません - Django は私たちのために作業を行い、私たちが意図した方法でデータベースが更新されるように支援します。

重要なのは、Django が多くの理由でこれらの変更を行うのに失敗するかもしれないことです。新しい Django 開発者の場合、ほとんどの場合、フィールドやカラムを追加したり削除 したり、migrations を正しく実行できなかったりすることが原因です。

正しく行うことで python manage.py migrate は、私たちのPython コードと SQL テーブルをマッチさせる安定したシステムを保証し、Django と SQL データベースの両方が提供する全ての素晴らしさを可能にします。

どのように柔軟性を高めているのでしょうか?

Python は、SQLにはない幅広い用途があります。Structured Query Languageは 名前に限界が書いてあります。SQLだけでピクサーのアニメーションを作っている人がいるんですか?

つまり、Python のシンプルさは、開発者が SQL のパワーを知らず知らずのうちに取り入れるのに役立つということです。

なぜマネージドデータベースとDjangoは意味があるのか?

Djangoを含むWebアプリケーションを作るとなると、いくつかのことを決めておく必要があります。

  • どのデータ・ストレージ・ソリューションが必要か?MySQL、Postgres、MongoDB、Redis、Object Storage など。
  • データストレージソリューションとの連携/運用はどうするのか?
  • 中断やダウンタイムからどのように回復するのか?
  • ストレージソリューションのメンテナンスはどうするのか?
  • ストレージソリューションのセキュリティはどのように確保するのか?
  • ストレージソリューションのバックアップはどうするのか?

これらの質問に対する答えは、プロジェクトが複雑になるにつれて変わってくるかもしれませんが、すべて同じところから始まります。

自己管理されている

  • 長所コントロールとコスト。
  • (有意)コン:全てに責任がある。

マネージドサービスは最初からコストがかかることが多いのですが、セルフマネージメントでは、必要なものに対して何らかの形で(あるいはある程度)最適化された、好みのLinuxディストロを使うことができるのです。これには、あなたのチームが変更したMySQLのフォークバージョンを実行することも含まれます。サービスの運営にかかる費用は節約できるかもしれませんが、その分、メンテナンスに時間がかかることになります。

サードパーティ製マネージド・データベース 

確かに、ドルやセントでは若干高くつくかもしれませんが、メンテナンスにかかる時間は大幅に短縮されます。このオプションとマネージドデータストレージソリューションは、私のWebアプリケーションのためのデファクトチョイスです。この例では、データベーストランザクションを管理するために、すでに Django を利用しています。SQLAlchemy もまた、FastAPI, Flask, その他多くのフレームワークと一緒に使われるので、この強みを共有しています。もしあなたが既に SQL を書くのをPython パッケージにアウトソーシングしているなら、SQL サーバを動かすのもアウトソーシングしてはどうでしょう?

さて、Python ORMs (Django ORM や SQLAlchemy など) の有効性を考えると、可能な限りマネージドデータベースおよび/またはマネージドデータストレージサービスを使うことをお勧めします。

  • 開発期間の短縮
  • 管理時間の短縮
  • 回復時間の短縮
  • サービス中断の低減
  • デプロイメントと開発の複雑さを軽減
  • 他サービスからのデータベース移行の複雑さを軽減します。
  • SQL開発者の反復的/非効率的/非効率的な作業を削減します。
  • DevOps/Opsの複雑性を軽減
  • SQL以外の開発者の効率アップ
  • デプロイメントと開発スピードの向上
  • 信頼性の向上(多くの場合、サービスレベルアグリーメントの裏付けがある)
  • セキュリティの強化
  • 保守性の向上
  • バックアップと冗長性の向上
  • 限界費用額の増加

上記のリストは、Linode上のマネージドMySQLデータベースクラスタを使用することを念頭に置いて作成しました。 Object Storage(CSS、JavaScript、画像、動画などのファイル保存用)を使うことを念頭に置いて、上記のリストを作りました。実用的に言えば、これらのサービスを使うことで、Django、FastAPI、Flask、Node.js などで優れたウェブアプリケーションを構築することに集中し続けることができます。別の言い方をすれば、ユーザが実際に欲しがるツールやソフトウェアを構築すること に焦点を移すのです。つまり、ユーザーにとって本当に価値のあるものです。

MySQL、PostgreSQL、Redis、およびDjango

長い間、Django の代表的なデータベースは PostgreSQL でした。これは、PostgreSQL 内だけで JSONField が使えたことが大きな理由であると主張したい。Django 3.2+ と MySQL 5.7.8+ で、JSONField は MySQL でも使用できるようになりました。

なぜそれが重要なのか?

JSONのような非構造化データの保存は、ユーザーが作成したコンテンツを扱ったり、他のサービスからのデータを保存したりする際に、しばしば必要となる。 API JSONのような非構造化データの保存は、ユーザーが作成したコンテンツを扱ったり、他のサービスからのデータを保存したりする際に必要になることが多い。方法を見てみよう:

from django.db import models

class Pet(models.Model):
    name = models.CharField(max_length=200)
    data = models.JSONField(null=True)

    def __str__(self):
        return self.name

このPetに関連して保存したいデータは以下の通りです。

pet1 = {
    "name": "Bruno",
    "type": "Rat",
    "nickname": "We don't talk about it",
    "age": 2,
    "age_interval": "months"
}

pet2 = {
    "name": "Tom",
    "type": "Cat",
    "breed": "Mixed"
    "age": 4,
    "age_interval: "years",
    "favorite_food": [{"brand": "Acme", "flavor": "Tuna" }]
}

pet3 = {
    "name": "Stewey",
    "type": "Dog",
    "breed": "unknown"
    "age": 34,
    "age_interval: "dog years",
    "nickname": "Football"
}

このデータは、私たちがどのような場合に必要なのかを示しています。 JSONField .すべてのペットの名前を保存することができます ( name キー)に格納し、残りはJSONFieldに格納するようにします。のクールな点は JSONFields は、このような様々なスキーマがあっても、他の標準的な Django のフィールドと同じように問い合わせることができます。

Django の開発者の間では、どのデータベースを使うかについて議論が続いています。MySQLPostgreSQL かです。長い間、JSONField がPostgreSQL上でしか使えないという理由から、私はいつも PostgreSQLを選んでいましたが、それはもう事実ではありません。私は、どちらかを選び、それがあなたのニーズに合わなくなるまで、それを使い続けることをお勧めします。

しかし、Redisは何に使うのでしょうか?

Redisは非常に高速なインメモリデータストアで、しばしば一時データベース(詳しくは後述します)、キャッシュサービス、メッセージングキューとして使用されます。一時的なデータベースと呼ぶのは、インメモリであることが理由です。メモリはディスクストレージよりも高価であるため、データを長期にわたってメモリに保存することは現実的でない場合が多い。

Redis と Django の主な使用目的は、キャッシュとキューイングです。

キャッシュ:ユーザーがよく訪れるウェブページがいくつかあるとします。それらのページのデータをできるだけ早くユーザに見せたい と思います。Django のキャッシュシステムである Redis は、これを非常に簡単に実現します。これらのページ内のデータは SQL データベースからレンダリングされるかもしれませんが、 Redis はキャッシュからそのレンダリングデータを保存することができます。言い換えれば、Redis を SQL と一緒に使うことで、SQL データベースへの問い合わせの量を減らしつつ、レスポンスを高速化できることが多いのです。

キューイング。Redisのもう一つの一般的な使用例は、長時間実行されるタスクを別のプロセスにオフロードすることです(多くの場合、CeleryというPython パッケージを使用します)。このような場合、Redisを別の時間に完了すべきタスクのキューとして使用することができます。

例えば、過去5年間の全取引のレポートを必要とするユーザーがいたとして、そのレポートを実際に作成するのに何時間もかかるかもしれません。もちろん、何時間もマシンとにらめっこしている人はいないでしょう。そこで、このユーザーからのリクエストをRedisキューにオフロードすることにしました。Redis に入ったら、実際にレポートを生成するためにワーカープロセスを走らせることができます (Django で Celery を使うのと同じです)。レポートが完成したら、それがどれだけ時間がかかったとしても、ユーザに通知されます。この通知は、他の通知と同様に、Celery/Django のワーカープロセスと結合した Redis Queue を通して行うことも可能でしょう。

これはすべて、Redisと MySQLが実際にお互いを非常によく補完し合っているということを言いたいのだ。LinodeのMarketplace

Object Storage

データ関連のマネージド・サービスで最後に利用をお勧めするのは、LinodeObject Storage 。Object Storage は、保存する必要のある他のすべての種類のデータを担当する。たとえば、ビデオのすべてのバイトをMySQLに格納することはない。その代わりに、そのビデオに関連するメタデータを保存し、ビデオをObject Storage に保存する。

ここでは、オブジェクトストレージの使い方をいくつか紹介します。

  • カスケーディングスタイルシート(CSS)
  • JavaScript(React.js、Vue.js、Vanilla.jsなど)。
  • ビデオ
  • Images (生と圧縮)
  • CSV、XLSX
  • データベースBackups
  • Docker コンテナのイメージレイヤー(自己管理の場合)
  • 訓練済み機械学習アルゴリズムの反復処理
  • Terraform ステートファイル
  • PDF(大・小とも)
  • 頻繁にダウンロードする(またはアップロードする)必要がある永続的なファイル

まとめ

これを読んだ後、あなたのウェブ・アプリケーション・プロジェクトでマネージドサービスのパワーを活用しようという気持ちになることを期待しています。Django は SQL データベース上にウェブアプリケーションを構築するための優れたソリューションですが、それが唯一のものではないことも確かです。SQL と SQL サーバについて詳しく知りたいのなら、多くのアプリケーションがどのように Django を活用して Django ができることの大部分を処理しているのかを確認すると良いと思います。

ここでは、Django with Managed MySQL on Linode を素晴らしいものにしているものをいくつか(あるいは数多く)紹介します。

  • Django は負担の多い SQL の仕事を代行してくれます(Flask/FastAPI 用の SQLAlchemy のようなツールも同様です)
  • Django は生の SQL コマンドも使えます(繰り返しますが、SQLAlchemy のようなツールも同様です)
  • Django は、初心者の SQL コマンドの習得を支援します
  • Django は MySQL と PostgreSQL をビルトインでサポートしています(さらに DB 固有の python クライアントもあります)
  • 本番環境への導入速度を向上
  • 信頼性・復旧性の向上
  • 開発環境と本番環境をデータベース技術にほぼ完全に一致させることが可能
  • コンテナベースのDjangoをより簡単に、より信頼性の高いものにします。
  • シングルノードからマルチノード、さらにはKubernetesへの本格的な移行まで、スケーラビリティを解放します。
  • 新しい Django/Python の開発者が、プロダクショングレードのシステムをより簡単に使用できるようになります。
  • 複数のpython- ベースのアプリ間でデータベースを共有することがより簡単で、より安全です (例えば、 FastAPI アプリケーションが Django ベースの MySQL データベースから/への読み込み/書き込みをするような場合)。
  • Django の JSONField が MySQL を使ってサポートされるようになりました (以前は PostgreSQL だけでした)。
  • テストが容易(CI/CD時やローカル開発環境において)
  • Django の要求に応えるための拡張性
  • 例えば、1つの Django プロジェクトで複数のデータベースをサポートします: MySQL をプライマリリード/ライトデータベースとして使用し、一般的なクエリのために MySQL リードレプリカデータベースを使用します。
  • 厳密なアクセス制御(LinodeのプライベートIP、ローカル開発)
  • 接続にSSL証明書が必要(導入が複雑になるが、セキュリティも向上する)
  • プライベート接続が可能(同一地域内、接続コスト低減)

もしあなたが、Linode上のDjangoアプリケーションを、マネージドMySQLデータベース、CI/CDのためのGitHub Actions、Terraform 、そしてAnsible と共にデプロイする最新のアプローチに興味があるなら、無料のステップバイステップの教育コンテンツのトンに飛び込んでみてください。

Coding for EntrepreneursのGitHubには、このシリーズの各ステップに対応するコードのリポジトリがあります。また、Twitterの@JustinMitchelで状況をお知らせください。


コメント 

コメントを残す

あなたのメールアドレスは公開されません。必須項目には*印がついています。