aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

Đọc PostgreSQL EXPLAIN ANALYZE: đừng nhầm cost với mili giây

Suong Nguyen by Suong Nguyen
24/10/2026
in Backend
0
585
SHARES
3.2k
VIEWS
Summarize with ChatGPTShare to Facebook

Một truy vấn chậm khiến bạn mở execution plan, thấy cost lớn rồi kết luận database mất từng ấy mili giây. Nếu bắt đầu từ cách đọc này, những lần so sánh sau rất dễ sai. Cost là ước lượng của planner; thời gian thực tế chỉ xuất hiện khi bạn chạy phép đo phù hợp.

Bài này hướng dẫn một vòng quan sát trước và sau khi thêm index trên bảng thử. Phạm vi tài liệu là PostgreSQL 17, đối chiếu ngày 24/10/2026. SQL đã được rà theo tài liệu nhưng chưa chạy trên PostgreSQL trong lượt biên tập; bài không cung cấp plan hoặc thời gian đo giả định.

Điều kiện cần có

Bạn cần một database thử nghiệm và quyền tạo bảng tạm. Chạy các lệnh trong cùng một phiên psql vì bảng tạm thuộc phiên đó. Không dùng dữ liệu production cho lần làm quen này. Ghi phiên bản bằng SELECT version(); cùng với kết quả plan để lần sau còn đối chiếu.

1. Tạo dữ liệu có thể làm lại

Fixture bên dưới tạo 10.000 hàng với 100 giá trị workspace. Đây là phân bố được dựng để học cách đọc plan, không đại diện cho tải thật của ứng dụng.

CREATE TEMP TABLE plan_demo (
    id integer PRIMARY KEY,
    workspace_id integer NOT NULL,
    body text NOT NULL
);

INSERT INTO plan_demo (id, workspace_id, body)
SELECT n, n % 100, repeat('x', 100)
FROM generate_series(1, 10000) AS n;

ANALYZE plan_demo;

EXPLAIN
SELECT id
FROM plan_demo
WHERE workspace_id = 7
ORDER BY id
LIMIT 20;

ANALYZE cập nhật thống kê để planner ước lượng phân bố dữ liệu. Bạn có thể đọc thêm về mục đích của lệnh trong tài liệu ANALYZE. Việc gọi nó ở đây cũng giúp bạn không vô tình so sánh plan trước và sau index trong hai trạng thái thống kê khác nhau mà không ghi nhận.

2. Tách ước lượng khỏi việc thực thi

Theo hướng dẫn sử dụng EXPLAIN, cost=a..b là chi phí khởi động và tổng chi phí ước lượng bằng đơn vị nội bộ. rows là số hàng node dự kiến trả ra; width là kích thước hàng trung bình ước lượng. Tổng cost của node cha đã bao gồm phần việc bên dưới, vì vậy không cộng toàn bộ cây như hóa đơn độc lập.

Để lấy dữ liệu thực thi, chạy:

EXPLAIN (ANALYZE, BUFFERS)
SELECT id
FROM plan_demo
WHERE workspace_id = 7
ORDER BY id
LIMIT 20;

EXPLAIN ANALYZE thực sự chạy câu lệnh. Tham chiếu EXPLAIN mô tả các tùy chọn và tác động này. Với bài học, chỉ dùng SELECT trên bảng thử. Đừng thêm ANALYZE một cách vô thức trước UPDATE hay DELETE; tác dụng của câu lệnh vẫn xảy ra. Ngay cả SELECT trên hệ thống thật cũng có thể tốn tài nguyên hoặc gọi hàm có tác động riêng.

3. Đọc từ sai lệch cụ thể

Trên kết quả của bạn, chọn node truy cập bảng và đối chiếu rows ước lượng với actual rows. Sai lệch lớn gợi ý cần tìm hiểu thống kê hoặc đặc điểm dữ liệu trước khi áp dụng mẹo thêm index. Với node có loops lớn hơn một, số hàng và thời gian thực tế được hiển thị theo trung bình mỗi lần thực thi; đọc cả số vòng lặp mới thấy quy mô công việc.

Buffers giúp bạn nhìn hoạt động truy cập bộ đệm. shared hit không phải một lần đọc đĩa; shared read cũng không đủ để khẳng định thiết bị lưu trữ vật lý vừa được đọc, vì còn cache ở tầng hệ điều hành. Hãy lưu nguyên output để tránh làm mất bối cảnh bằng cách chụp riêng một con số.

Phần thống kê của planner giúp giải thích vì sao ước lượng phụ thuộc dữ liệu thống kê. Tuy nhiên, một lần thấy estimated rows khác actual rows chưa tự chứng minh nguyên nhân duy nhất là thiếu ANALYZE.

4. Thêm index rồi quan sát lại

CREATE INDEX plan_demo_workspace_id_idx
ON plan_demo (workspace_id, id);

ANALYZE plan_demo;

EXPLAIN (ANALYZE, BUFFERS)
SELECT id
FROM plan_demo
WHERE workspace_id = 7
ORDER BY id
LIMIT 20;

Index được chọn làm ứng viên vì truy vấn lọc theo workspace rồi lấy ID theo thứ tự. Nó không buộc planner phải dùng index scan. Giữ nguyên câu SELECT, lưu hai plan và ghi tình trạng cache cùng môi trường. Nếu không thấy cải thiện, hãy coi đó là kết quả cần giải thích, không sửa số liệu cho khớp kỳ vọng.

Kiểm tra và lỗi thường gặp

Đầu tiên xác nhận SELECT vẫn trả đúng dữ liệu cần lấy. Sau đó so sánh kiểu scan, việc sort, số hàng bị lọc và loops. Tách câu hỏi “plan có đổi không?” khỏi “độ trễ của luồng ứng dụng có giảm không?”. Fixture nhỏ trong một phiên không đo được ảnh hưởng của nhiều request đồng thời, mạng hay pool kết nối.

Đừng cộng thời gian cha và con vì chúng có phần chồng nhau. Đừng gọi mọi sequential scan là lỗi; với lượng dữ liệu và độ chọn lọc cụ thể, đó có thể là lựa chọn hợp lý. Cũng đừng lấy kết quả chạy lần hai sau khi cache nóng để khẳng định index đã tạo ra toàn bộ mức thay đổi.

Gợi ý tiếp theo

Chọn một truy vấn thật đã được làm sạch thông tin riêng tư, ghi tham số và plan trong môi trường thử đại diện hơn. Mục tiêu đầu tiên là giải thích được đường đi của dữ liệu và điểm ước lượng sai, rồi mới quyết định tối ưu. Cách đọc có bối cảnh hữu ích hơn việc săn một giá trị cost nhỏ.

Nguồn tham khảo

  • PostgreSQL 17: sử dụng EXPLAIN
  • PostgreSQL 17: tham chiếu EXPLAIN
  • PostgreSQL 17: ANALYZE
  • PostgreSQL 17: thống kê planner

Tags: Hiệu năngPostgreSQLSQL
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

Optimistic locking trong PostgreSQL: tránh ghi đè thay đổi của người khác

by Suong Nguyen
23/10/2026
0

Dùng cột version và UPDATE có điều kiện để phát hiện một biểu mẫu đang lưu trên phiên bản dữ liệu đã cũ.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

Idempotency-Key cho API tạo đơn: retry mà không tạo trùng nghiệp vụ

by Suong Nguyen
22/10/2026
0

Thiết kế phạm vi khóa, transaction và response lưu lại để API tạo đơn xử lý an toàn khi client gửi lại request.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

Phân trang keyset trong PostgreSQL bằng created_at và id

by Suong Nguyen
21/10/2026
0

Dùng cặp created_at và id làm mốc phân trang, tránh thứ tự không xác định và hiểu giới hạn của keyset khi dữ liệu thay đổi.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

Thiết kế backend API gọn gàng cho sản phẩm nhỏ

by admin
02/07/2026
0

Một backend API tốt cho sản phẩm nhỏ không cần quá phức tạp, nhưng phải rõ resource, validate kỹ, trả lỗi nhất quán và dễ mở rộng.

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native useWindowDimensions: layout đổi chiều và vẫn đọc được chữ lớn
  • Promise.all và allSettled: chờ kết quả không có nghĩa là tự hủy tác vụ
  • Android SavedStateHandle: giữ bộ lọc khi process bị hệ thống tạo lại

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply