SQL Formatter khi review PR & log ORM | Pretty-print trước EXPLAIN

(Cập nhật: 19 tháng 7, 2026 ) SQL formatter pretty-print ORM code review EXPLAIN outsourcing
Kết luận

Trước khi tranh luận index hay đổ lỗi ORM, hãy pretty-print SQL. Log một dòng từ Prisma / Eloquent / TypeORM che mất JOIN và điều kiện — format xong mới đọc EXPLAIN mới hiệu quả. Team outsourcing nên thống nhất: keyword HOA + indent theo mệnh đề; dùng Định dạng SQL trên trình duyệt khi review PR hoặc dán log nhạy cảm (không upload DB production lên dịch vụ lạ).

Outsourcing và freelancer backend ở Việt Nam review PR hàng ngày với SQL đến từ query builder / ORM, không phải file .sql viết tay. Reviewer mở diff thấy:

const users = await prisma.user.findMany({ include: { orders: true }, where: { ... } });

Nhưng bug nằm ở SQL thật ORM sinh ra — thường chỉ xuất hiện khi bật log: một dòng SELECT ... JOIN ... WHERE ... dài hàng nghìn ký tự. Bảo “nhìn EXPLAIN” mà chưa format = đoán mò.

Bài viết này giúp bạn

  • Hiểu khi nào pretty-print quan trọng hơn chỉnh ORM
  • Áp dụng convention cho team nhiều quốc gia / nhiều style
  • Phân biệt Format vs Minify
  • Gắn SQL đã format vào PR / ticket / post-mortem
  • Tránh paste secret và PII lên tool online không rõ nguồn

Pain: ORM log một dòng

Ví dụ (rút gọn) giống log thật:

select u.id, u.name, o.order_date, p.product_name from users u join orders o on u.id = o.user_id join products p on o.product_id = p.id where o.status = 'completed' and o.created_at > '2025-01-01' order by o.created_at desc limit 100;

Ở dạng này, reviewer khó trả lời nhanh:

  • JOIN products có cần không nếu chỉ đếm order?
  • created_at đã có index chưa?
  • LIMIT có đi với ORDER BY ổn không?

Sau khi format:

SELECT
  u.id,
  u.name,
  o.order_date,
  p.product_name
FROM
  users u
  JOIN orders o ON u.id = o.user_id
  JOIN products p ON o.product_id = p.id
WHERE
  o.status = 'completed'
  AND o.created_at > '2025-01-01'
ORDER BY
  o.created_at DESC
LIMIT
  100;

Cấu trúc lộ ngay: hai JOIN, hai điều kiện, sort + limit. Bước mắt này nên đứng trước EXPLAIN — plan không thay thế việc hiểu query đang làm gì.


Format vs Minify vs “để nguyên log”

Chọn chế độ theo việc đang làm
Chế độ Dùng khi Không dùng khi
Format (pretty) Review PR, debug chậm, viết ticket, đọc trước EXPLAIN Nhúng vào chuỗi một dòng trong shell thô
Minify (1 dòng) Gán vào biến script, một số tool CLI, so sánh hash chuỗi Lưu trong repo để người đọc
Log thô ORM Chỉ để copy nhanh từ console Paste thẳng vào PR không format

Convention gợi ý cho team outsourcing

Ghi vào CONTRIBUTING.md hoặc wiki ngắn:

  1. KEYWORD viết HOASELECT, FROM, JOIN, WHERE, AND, ORDER BY
  2. Mỗi cột một dòng khi SELECT > 3 cột
  3. JOIN và ON cùng khối nhìn thấy điều kiện gắn kết
  4. AND/OR căn lề dưới WHERE
  5. Ticket hiệu năng đính SQL đã format + plan (text hoặc ảnh)

Không cần tranh “comma-first vs comma-end” nếu team chưa pain — chọn một và giữ ổn định quan trọng hơn.


Workflow: từ log ORM → EXPLAIN

  1. Bật log trên staging (Prisma query, Laravel telescope/DB::listen, TypeORM logging).
  2. Reproduce đúng API/job chậm.
  3. Copy SQL — nếu log còn ? placeholder, bind giá trị mẫu an toàn (không phải production secret).
  4. Format bằng Định dạng SQL Kawa (Format + tùy chọn viết hoa từ khóa).
  5. Đọc cấu trúc 30–60 giây: bảng nào, filter nào, sort nào.
  6. EXPLAIN / EXPLAIN ANALYZE trên bản đã hiểu.
  7. Sửa ở đúng lớp: index, select thừa, N+1, hoặc rewrite query.

Công cụ chạy trong trình duyệt — phù hợp khi SQL có tên bảng nội bộ; vẫn nên che email/SĐT/token trước khi chia sẻ screenshot.

🗃️ Định dạng SQL ngay tại đây

  

Case study 1: PR “thêm filter” làm chậm list đơn hàng

Bối cảnh: Team VN outsource cho client JP. Dev thêm where: { status, shopId, createdAt } trong Prisma. API list từ 80ms → 1.2s trên staging.

Sai: Mở thẳng EXPLAIN trên chuỗi một dòng, tranh luận index status trong khi bỏ sót JOIN bảng shops không dùng trong SELECT.

Đúng: Format → thấy JOIN shops thừa từ include cũ. Bỏ include, thêm composite index (shop_id, created_at). PR mô tả kèm SQL pretty — reviewer approve trong một vòng.


Case study 2: Hai dev, hai style SQL trong cùng service

Một người viết keyword thường, người kia HOA; một người indent subquery kiểu C, người kia để một dòng. Diff Git gần như không đọc được dù logic giống nhau.

Fix quy trình: Mọi raw SQL trong *.sql / string dài phải format trước khi commit; CI không bắt buộc formatter SQL, nhưng checklist PR có mục “SQL đã pretty?”. Dùng chung tool browser khi pair remote — không cãi IDE plugin khác nhau.


Khi formatter “hỏng” output

  • Quote chưa đóng / ngoặc lệch → sửa tay trước.
  • Dialect riêng (hint SQL Server, ::jsonb Postgres phức tạp) — format có thể không đẹp hoàn hảo; vẫn đủ để đọc khối chính.
  • Query cực lớn (DDL hàng nghìn dòng) — tách phần đang debug; đừng dán cả dump.

Formatter không thay linter SQL hay migration tool. Nó thay bước đọc bằng mắt.


Checklist gắn vào PR hiệu năng / raw SQL

  • SQL trong mô tả PR đã pretty-print
  • Keyword theo convention team
  • Đã che PII / secret
  • Có EXPLAIN (hoặc lý do chưa chạy được)
  • Nêu giả thuyết: index / JOIN thừa / N+1 / sort file

Công cụ liên quan

SQL chậm không chờ “cảm giác”. Nhìn thấy cấu trúc rồi mới tối ưu — pretty-print là bước rẻ nhất trong chuỗi đó.