---
title: "データベースの計測"
version: 5.1
locale: ja
source: https://docs.djangoproject.com/ja/5.1/topics/db/instrumentation/
canonical: https://djangodocs.dev/ja/5.1/topics/db/instrumentation/
---
# データベースの計測

コードから発行されたクエリを理解して制御するために、Django は、データベースクエリの実行周辺にラッパー関数をインストールするためのフックを提供しています。たとえば、ラッパーは、クエリのカウント、クエリの実行時間の測定、クエリのログ、さらにクエリの実行の防止までもできます (たとえば、プリフェッチされたデータを使用してテンプレートをレンダリングする間にクエリが発行されないようにするため)。

ラッパーは [ミドルウェア](/ja/5.1/topics/http/middleware/) にならったもので、別の呼び出し可能オブジェクトを引数の1つとして受け取ります。ラッパーはデータベースクエリ(ラップされている可能性があります)を呼び出すために callable を呼び出します。しかし、これらはユーザーコードによって作成され、インストールされるため、ミドルウェアのように個別のファクトリを必要としません。

ラッパーのインストールは、コンテキストマネージャで行われます。そのため、ラッパーは一時的なもので、コード内の特定のフローに特化したものです。

前述したように、ラッパーの例はクエリ実行ブロッカーです。以下のようなものです:

```
def blocker(*args):
    raise Exception("No database access allowed here.")
```

そして、テンプレートからのクエリをブロックするには、ビューでこのように使用します:

```
from django.db import connection
from django.shortcuts import render

def my_view(request):
    context = {...}  # Code to generate context with all data.
    template_name = ...
    with connection.execute_wrapper(blocker):
        return render(request, template_name, context)
```

ラッパーに送られるパラメーターは以下の通りです:

- `execute` -- クエリを実行するために、残りのパラメータと一緒に呼び出される呼び出し可能オブジェクト。
- `sql` -- データベースに送信する SQL クエリの `str`。
- `params` -- SQL コマンドのパラメータ値のリストまたはタプル、または、ラップされた呼び出しが `executemany()` の場合はリストまたはタプルのリストまたはタプル。
- `many` -- 最終的に呼び出すのが `execute()` なのか `executemany()` なのかを示す `bool` (`params` が値のシーケンスなのか、値のシーケンスのシーケンスなのかを示します)。
- `context` -- 呼び出しのコンテキストに関するデータを含む辞書。これにはコネクションとカーソルが含まれます。

このパラメータを使用することで、次のように、もう少し複雑なバージョンのブロッカーで、エラーメッセージにコネクション名を含めることができます。

```
def blocker(execute, sql, params, many, context):
    alias = context["connection"].alias
    raise Exception("Access to database '{}' blocked here".format(alias))
```

より完全な例として、クエリロガーは次のようになります。

```
import time

class QueryLogger:
    def __init__(self):
        self.queries = []

    def __call__(self, execute, sql, params, many, context):
        current_query = {"sql": sql, "params": params, "many": many}
        start = time.monotonic()
        try:
            result = execute(sql, params, many, context)
        except Exception as e:
            current_query["status"] = "error"
            current_query["exception"] = e
            raise
        else:
            current_query["status"] = "ok"
            return result
        finally:
            duration = time.monotonic() - start
            current_query["duration"] = duration
            self.queries.append(current_query)
```

これを使用するには、ロガーオブジェクトを作成し、ラッパーとしてインストールします。

```
from django.db import connection

ql = QueryLogger()
with connection.execute_wrapper(ql):
    do_queries()
# Now we can print the log.
print(ql.queries)
```

## `connection.execute_wrapper()`

#### `execute_wrapper(wrapper)`

入力すると、データベースクエリ実行の周囲にラッパーをインストールし、終了するとラッパーを削除するコンテキストマネージャを返します。ラッパーはスレッドローカルのコネクションオブジェクトにインストールされます。

`wrapper` は5つの引数を取る呼び出し可能オブジェクトです。 上記のように、 `execute`, `sql`, `params`, `many`, `context` を引数として、コンテキストマネージャのスコープ内でクエリを実行するたびに呼び出されます。 `execute(sql、params、many、context)` を呼び出して、その戻り値を返すことが期待されます。
