Запросы и индексация активности тикетов

CloudflareBeginner
Практиковаться сейчас

Введение

Сотрудникам поддержки нужна хронология событий для каждого тикета и сводка, в которую также входят тикеты без событий. Вы свяжете строки активности с тикетами, создадите повторно используемый SQL-отчёт и добавите индекс, обоснованный планом запроса. Быстрый ответ на крошечном наборе данных сам по себе не доказывает, что выбран эффективный путь доступа.

В этой самостоятельной лабораторной работе используется базовая схема тикетов из предыдущих занятий. Вы самостоятельно создадите связь, отчёт и индекс в одной временной базе данных D1.

Используйте собственную учебную учётную запись и новую виртуальную машину. Сначала настройка установит Node.js 22.22.0, затем выполнит npm install для локального Wrangler 4.131.1 и зависимостей проверки в каталоге /home/labex/project/ticket-database. Версии прямых зависимостей зафиксированы; установка создаёт собственный lock-файл. Во время настройки вход в облако и операции с проверяемой базой данных не выполняются. На личном компьютере установите ту же версию Wrangler командой npm install --save-dev wrangler@4.131.1 в каталоге проекта.

В упражнении используются небольшие синтетические записи в пределах бесплатных лимитов D1. Текущее использование учётной записи также учитывается в этих лимитах. Покупать домен не нужно. Не удаляйте эту виртуальную машину, пока не проверите удаление ресурсов и выход из учётной записи.

Авторизуйте виртуальную машину и выберите учётную запись

На этом этапе вы подключите новый терминал к собственной учебной учётной записи. Одного входа в Dashboard недостаточно для авторизации виртуальной машины. Разрешение D1 позволяет создавать базы данных, изменять SQL-схему и удалять базы данных. Перед авторизацией просмотрите настоящую страницу согласия, включая пункт Background Access.

Откройте подготовленный проект и проверьте зафиксированную версию CLI:

cd /home/labex/project/ticket-database
npx wrangler --version

Ожидаемый результат — 4.131.1. Запустите авторизацию устройства. Параметр --device выводит код для браузера, а --browser=false позволяет вам самостоятельно выбрать способ открытия браузера:

npx wrangler login --device --browser=false --scopes account:read user:read d1:write

Откройте показанный URL в браузере, введите текущий код, подтвердите свою учебную учётную запись и разрешения, затем авторизуйте доступ. Дождитесь сообщения терминала об успешном завершении. Никогда не вставляйте пароли или токены в файлы проекта.

npx wrangler whoami --json

Убедитесь, что указано loggedIn: true, затем прочитайте name и id учётной записи, даже если в списке присутствует только одна учётная запись. Скопируйте нужный идентификатор в конфигурацию ниже. Следующая переменная оболочки использует 6 случайных байтов (12 шестнадцатеричных символов), чтобы избежать совпадений с другими учащимися. Here-document записывает JSON между строками JSON; переменная $RUN раскрывается внутри него.

Обратная косая черта перед $schema сохраняет этот ключ JSON буквально; $RUN по-прежнему подставляет уникальное имя текущего запуска.

RUN=labex-c04-d04-$(openssl rand -hex 6)
cat > wrangler.jsonc <<JSON
{
  "\$schema": "./node_modules/wrangler/config-schema.json",
  "name": "$RUN",
  "account_id": "YOUR_ACCOUNT_ID",
  "main": "src/index.js",
  "compatibility_date": "2026-09-15",
  "workers_dev": true,
  "preview_urls": false
}
JSON

Замените YOUR_ACCOUNT_ID перед выполнением блока. Не закрывайте этот терминал, чтобы переменная RUN оставалась доступной. Поле name идентифицирует текущий запуск, а account_id выбирает учётную запись для облачных операций. Этот файл является обычным JSON, который также соответствует формату JSONC. При его создании Worker не разворачивается.

Свяжите активности с тикетами

На этом этапе вы добавите таблицу активности, в которой для одного тикета будут представлены несколько событий. Внешний ключ связывает ticket_id активности с существующим тикетом и не позволяет событию ссылаться на отсутствующую родительскую запись. Настройка предоставляет знакомую схему тикетов, чтобы вы могли сосредоточиться на связях и запросах.

Создайте временную облачную базу данных. Параметр --binding DB задаёт короткое имя для обращения к базе из кода, --update-config записывает её настоящее имя и UUID в wrangler.jsonc, а --use-remote=false оставляет разработку локальной:

npx wrangler d1 create "$RUN-db" --binding DB --update-config --use-remote=false

Прочитайте имя и идентификатор созданной базы, затем проверьте сохранённую привязку:

cat wrangler.jsonc

Запись DB должна указывать на базу данных текущего запуска. Привязка — это настроенное соединение между кодом и ресурсом. Её UUID идентифицирует облачную базу данных, а параметр --local использует отдельную базу SQLite на этой виртуальной машине. В командах SQL всегда явно указывайте --local или --remote.

Прочитайте и примените предоставленную схему тикетов локально:

cat schema.sql
npx wrangler d1 execute DB --local --file schema.sql

Запишите схему активности и фиксированный набор данных. Целочисленные временные метки здесь служат синтетическими значениями для сортировки, а не обозначают текущее время:

cat > activity.sql <<'SQL'
CREATE TABLE activity (
  id INTEGER PRIMARY KEY,
  ticket_id INTEGER NOT NULL REFERENCES tickets(id),
  action TEXT NOT NULL,
  created_at INTEGER NOT NULL
);
INSERT INTO activity (id, ticket_id, action, created_at) VALUES
  (1, 1, 'opened', 100),
  (2, 1, 'assigned', 200),
  (3, 2, 'opened', 110),
  (4, 2, 'closed', 300);
INSERT INTO tickets (id, subject, source) VALUES (3, 'No activity yet', 'seed');
SQL

Примените изменения локально:

npx wrangler d1 execute DB --local --file activity.sql

Для тикетов 1 и 2 записано по два события, а у тикета 3 событий нет. На следующем этапе вы увидите, как включить тикет с нулевым числом событий в сводку.

Создайте отчёт об активности тикетов

На этом этапе вы объедините строки из двух таблиц. Объединение сопоставляет строки по связи между ними. t и a — короткие псевдонимы имён таблиц. LEFT JOIN сохраняет каждый тикет, даже если у него нет активности; COUNT(a.id) считает только идентификаторы совпавших событий. GROUP BY группирует события по тикету, а AS event_count задаёт имя вычисляемого столбца.

Запишите повторно используемый запрос только для чтения. Если хранить запрос в SQL-файле, один и тот же отчёт можно запускать локально и удалённо:

cat > report.sql <<'SQL'
SELECT t.id, t.subject, COUNT(a.id) AS event_count
FROM tickets AS t
LEFT JOIN activity AS a ON a.ticket_id = t.id
GROUP BY t.id, t.subject
ORDER BY t.id;
SQL

Запустите отчёт:

npx wrangler d1 execute DB --local --file report.sql

Ожидаемые значения — 2, 2 и 0 для тикетов 1, 2 и 3 соответственно. При использовании внутреннего объединения тикет 3 исчез бы из результата, а подсчёт * посчитал бы для него строку-заполнитель без совпадения. Прочитайте события одного тикета в хронологическом порядке:

npx wrangler d1 execute DB --local --command "SELECT action, created_at FROM activity WHERE ticket_id = 1 ORDER BY created_at;"

Ожидаемый результат: opened со значением 100, затем assigned со значением 200. Отчёт показывает количество событий у каждого тикета, а отфильтрованный запрос — какие события относятся к одному тикету.

Обоснуйте индекс с помощью плана запроса

На этом этапе вы добавите структуру для поиска событий в хронологии активности. Индекс хранит значения, по которым выполняется поиск, в определённом порядке и может избавить от просмотра несвязанных строк. Индекс занимает место и добавляет работу при изменении индексируемых значений, поэтому его следует создавать для конкретного запроса.

Сначала изучите план до добавления индекса. EXPLAIN QUERY PLAN описывает стратегию доступа SQLite, но не измеряет прошедшее время:

npx wrangler d1 execute DB --local --command "EXPLAIN QUERY PLAN SELECT action, created_at FROM activity WHERE ticket_id = 1 ORDER BY created_at;"

Найдите в выводе сканирование activity и, возможно, временную структуру для сортировки. Создайте составной индекс: сначала по ticket_id, затем по created_at:

cat > index.sql <<'SQL'
CREATE INDEX idx_activity_ticket_created ON activity(ticket_id, created_at);
SQL
npx wrangler d1 execute DB --local --file index.sql
npx wrangler d1 execute DB --local --command "EXPLAIN QUERY PLAN SELECT action, created_at FROM activity WHERE ticket_id = 1 ORDER BY created_at;"

Теперь в плане для поиска должно упоминаться idx_activity_ticket_created. Точный формат вывода может отличаться. Фиксированный набор данных слишком мал для полезного сравнения времени выполнения; здесь доказательством служит выбранный путь доступа.

Добавьте новое событие после создания индекса и снова запустите отчёт:

npx wrangler d1 execute DB --local --command "INSERT INTO activity (id, ticket_id, action, created_at) VALUES (5, 1, 'replied', 400);"
npx wrangler d1 execute DB --local --file report.sql

Теперь у тикета 1 три события. Индекс должен поддерживать не только чтение, но и корректную запись данных.

Запустите отчёт и запрос с индексом в D1

На этом этапе вы установите проверенные схему и индекс в удалённой лабораторной базе данных. Одних локальных файлов недостаточно для создания схемы в удалённой базе.

npx wrangler d1 execute DB --remote --file schema.sql
npx wrangler d1 execute DB --remote --file activity.sql
npx wrangler d1 execute DB --remote --file index.sql

При появлении запроса подтвердите только базу данных этой лабораторной работы. Добавьте то же последнее событие, проверьте отчёт и план удалённого запроса:

npx wrangler d1 execute DB --remote --command "INSERT INTO activity (id, ticket_id, action, created_at) VALUES (5, 1, 'replied', 400);"
npx wrangler d1 execute DB --remote --command "$(cat report.sql)"
npx wrangler d1 execute DB --remote --command "EXPLAIN QUERY PLAN SELECT action, created_at FROM activity WHERE ticket_id = 1 ORDER BY created_at;"

$(cat report.sql) передаёт текст отчёта как запрос. При использовании --file с удалённой базой применяется рабочий процесс импорта, поэтому выводятся метаданные импорта, а не таблица с результатом SELECT. Удалённый отчёт должен показать значения 3, 2 и 0, а в плане должен быть указан ваш индекс. Это подтверждает результат и путь доступа в D1 без предположения о конкретном ускорении. При необходимости откройте базу D1 этого запуска в Dashboard и выполните проверку таблицы или схемы в режиме только для чтения; доказательством индекса оставьте план CLI.

Активность обращений в D1 Studio

В этом примере показаны пять удалённых строк активности и их связи через ticket_id. Сгенерированное имя базы данных обозначает этот пример запуска; ваше имя будет другим. Числа created_at — синтетические значения для сортировки, а не текущие метки времени. Таблица служит визуальным ориентиром для строк; приведённый выше вывод CLI EXPLAIN QUERY PLAN подтверждает использование индекса, но не улучшение времени выполнения.

Удалите временные ресурсы

На этом этапе вы удалите только ресурсы этой лабораторной работы, пока виртуальная машина всё ещё авторизована. Сначала завершите все функциональные проверки. Не удаляйте конфигурацию, пока не проверите удаление.

npx wrangler d1 delete DB

Просмотрите запрос подтверждения и убедитесь, что удаляется только база данных текущего запуска. Затем выведите список баз данных:

npx wrangler d1 list --json

Имя и UUID записанной вами базы данных должны отсутствовать в успешном ответе. Другие ресурсы могут остаться. Ошибка аутентификации или сети не даёт заключения: восстановите доступ и повторите чтение списка перед продолжением. Выполните проверку этого этапа, пока вход в систему ещё активен.

Завершите авторизацию виртуальной машины

На этом этапе вы завершите авторизацию только после успешной независимой проверки удаления. Выход удаляет сохранённые на этой виртуальной машине данные авторизации Wrangler; одного закрытия виртуальной машины недостаточно для очистки облачных ресурсов.

npx wrangler logout
npx wrangler whoami --json

Ожидайте loggedIn: false. Неаутентифицированный запрос может завершиться с ненулевым кодом; это нормально только в том случае, если структурированный ответ явно сообщает, что вы вышли из системы. Завершите проверку, затем закройте лабораторную среду.

Резюме

Вы попрактиковались в создании запросов и индексации активности тикетов. Вы проверили наблюдаемые результаты базы данных, явно указали выбранную учётную запись и локальное состояние, а затем удалили временные ресурсы перед выходом из системы.