【SQL & データベース入門】Django ORMと生SQLの使い分け|パフォーマンスを意識したデータ操作

Django ORMとは何か?

Django ORMの概要

Django ORM(Object-Relational Mapping)は、Djangoフレームワークが提供するデータベース操作のための抽象化レイヤーです。データベースとのやり取りをPythonのオブジェクトとして操作することができ、SQLを書かなくてもデータの取得、挿入、更新、削除が行えます。

なぜORMを使うのか?

  • 簡潔なコード:SQLを直接書く代わりに、Pythonコードでデータベース操作が可能です。
  • データベースの切り替えが容易:異なるデータベースに変更する場合でも、ORMを使っていればコードの変更が最小限で済みます。
  • セキュリティの向上:SQLインジェクションなどの脅威に対する保護が組み込まれています。

生SQLとは何か?

生SQLの概要

生SQL(Raw SQL)とは、データベースに直接SQL文を送って操作する方法です。ORMを使わずに、カスタムSQLをそのまま実行するため、より柔軟で複雑なクエリを記述できます。

なぜ生SQLを使うのか?

  • 複雑なクエリに対応可能:複数のJOIN、集計、ウィンドウ関数などを含む複雑なクエリを記述する場合に適しています。
  • パフォーマンスの最適化:ORMでは最適化が難しいクエリに対して、手動で効率的なSQLを書けます。
  • 特殊なデータベース機能の利用:ORMがサポートしていないデータベース特有の機能を使う場合に有効です。

Django ORMの基本操作

モデルの定義

Djangoでは、モデルを定義することでテーブルとその構造を自動的に生成できます。

from django.db import models

class Employee(models.Model):
    name = models.CharField(max_length=100)
    department = models.CharField(max_length=50)
    salary = models.DecimalField(max_digits=10, decimal_places=2)

データの挿入

ORMを使って新しいレコードを挿入するには、モデルのインスタンスを作成して保存するだけです。

employee = Employee(name="田中太郎", department="営業", salary=500000)
employee.save()

データの取得

すべての従業員データを取得する場合:

employees = Employee.objects.all()

条件付きでデータを取得する場合:

sales_employees = Employee.objects.filter(department="営業")

データの更新

特定の従業員の給与を更新する場合:

employee = Employee.objects.get(id=1)
employee.salary = 600000
employee.save()

データの削除

特定の従業員を削除する場合:

employee = Employee.objects.get(id=1)
employee.delete()

生SQLの使用方法

生SQLの実行

Djangoで生SQLを使用するには、raw() メソッドを利用します。

from django.db import connection

employees = Employee.objects.raw('SELECT * FROM employees WHERE department = %s', ['営業'])
for employee in employees:
    print(employee.name, employee.salary)

カスタムクエリの実行

さらに柔軟なクエリが必要な場合は、connection.cursor() を使います。

with connection.cursor() as cursor:
    cursor.execute('SELECT COUNT(*) FROM employees WHERE salary > %s', [500000])
    result = cursor.fetchone()
    print("高給取りの従業員数:", result[0])

Django ORMと生SQLの違い

コードの簡潔さ

  • Django ORM:シンプルなCRUD操作に最適で、わかりやすいコードになります。
  • 生SQL:複雑な操作には必要ですが、コードが長くなりがちです。

柔軟性

  • Django ORM:基本的な操作においては十分に柔軟ですが、複雑なクエリでは制限があります。
  • 生SQL:どんなクエリでも記述可能で、データベース固有の機能も使えます。

パフォーマンス

  • Django ORM:大部分の操作で最適化されていますが、JOINや集計などでパフォーマンスが問題になることがあります。
  • 生SQL:手動で最適化が可能なため、大量データの操作や複雑なクエリで優れたパフォーマンスを発揮します。

Django ORMと生SQLの使い分け

Django ORMを使うべき場合

  • シンプルなCRUD操作が中心のアプリケーション。
  • 異なるデータベースに移行する可能性があるプロジェクト。
  • 開発速度や可読性を重視する場合。

生SQLを使うべき場合

  • 複雑なJOINや集計クエリが必要な場合。
  • ORMで効率的に記述できない高度なクエリが求められるとき。
  • パフォーマンスの最適化が重要なシステム。

実際の応用例

1. ECサイトでの商品検索

ECサイトでは、シンプルな検索にはDjango ORMを、複雑な絞り込みやランキングには生SQLを使い分けます。

# Django ORMを使った基本的な検索
products = Product.objects.filter(category="electronics", price__lte=50000)

# 生SQLを使ったカスタム検索
with connection.cursor() as cursor:
    cursor.execute('SELECT * FROM products WHERE category = %s AND price <= %s ORDER BY popularity DESC', ['electronics', 50000])
    results = cursor.fetchall()

2. 大規模なデータ分析

ビジネス分析やレポート生成など、大量のデータを集計する場面では生SQLが有効です。

with connection.cursor() as cursor:
    cursor.execute('''
    SELECT department, AVG(salary) AS avg_salary
    FROM employees
    GROUP BY department
    HAVING avg_salary > %s
    ''', [400000])
    for row in cursor.fetchall():
        print(f"部署: {row[0]}, 平均給与: {row[1]}")

まとめ

Django ORMと生SQLは、それぞれの特性を理解し、適切に使い分けることが重要です。一般的なCRUD操作や基本的な検索にはDjango ORMが便利ですが、複雑なクエリやパフォーマンスが重要な場面では生SQLが有効です。システムの要件やパフォーマンスのニーズに応じて、両者を効果的に組み合わせることで、最適なデータベース操作を実現しましょう。