Cửa hàng đã có 20.000 khách hàng. Nhân viên hỗ trợ muốn tìm người có tên “Khách hàng 15000”, nhưng mỗi lần tìm, hệ thống lại phải kiểm tra một lượng dữ liệu lớn. Làm sao giúp PostgreSQL tìm đúng chỗ mà vẫn trả về đầy đủ kết quả?
Bắt đầu từ một truy vấn quen thuộc
Trong lab, bạn dùng bộ dữ liệu shop@v3. Bảng khach_hang có các cột id, ho_ten, email, thanh_pho và ngay_tao. Thử tìm một khách theo tên:
SELECT id, ho_ten
FROM khach_hang
WHERE ho_ten = 'Khách hàng 15000';
Kết quả chỉ có một dòng. Tuy nhiên, một dòng kết quả không có nghĩa là database chỉ kiểm tra một dòng. Bạn có thể hỏi PostgreSQL đã chọn cách tìm nào bằng cách thêm EXPLAIN trước truy vấn:
EXPLAIN
SELECT id, ho_ten
FROM khach_hang
WHERE ho_ten = 'Khách hàng 15000';
Khi chưa có index trên ho_ten, lab này hiện Seq Scan: quét lần lượt dữ liệu trong bảng và kiểm tra điều kiện. Cột tên chưa có ràng buộc duy nhất, nên PostgreSQL phải tiếp tục tìm các dòng khác cũng có tên đó. Một truy vấn có LIMIT có thể dừng sớm; truy vấn đang xét không có LIMIT.
Tên khách không nói lên vị trí lưu. “Khách hàng 15000” không có nghĩa PostgreSQL được phép nhảy tới dòng thứ 15.000 rồi bỏ qua phần còn lại. Thứ tự vật lý của dữ liệu có thể thay đổi khi bảng được cập nhật.
Dữ liệu được lưu theo trang
PostgreSQL chia dữ liệu thành các khối có kích thước cố định, thường là 8 KB, gọi là trang. Một trang chứa được nhiều dòng; số dòng cụ thể phụ thuộc kích thước dữ liệu. Vì vậy, không thể lấy số dòng rồi chia cho một hằng số để biết chính xác số trang của mọi bảng. Tài liệu về cách lưu trang.
Khi tìm kiếm, PostgreSQL có thể lấy trang từ bộ nhớ đệm hoặc phải đọc từ nơi lưu trữ. Số trang cần truy cập là một phần quan trọng của công việc, nhưng tốc độ còn phụ thuộc việc so sánh, sắp xếp, dữ liệu đã có trong bộ nhớ hay chưa và các bước khác của truy vấn.
Trong mô phỏng, bảng được thu nhỏ thành 12 trang để bạn dễ quan sát. Những trang này minh họa cơ chế tìm kiếm. Chúng không phải bản sao vị trí lưu của toàn bộ 20.000 khách trong lab. Hãy tách câu hỏi “database tìm theo cách nào?” khỏi câu hỏi “lần chạy này đo được bao nhiêu lượt truy cập?”.
Viết lệnh ở ô bên phải rồi bấm Chạy (Ctrl + Enter). Kết quả và mô phỏng hiện ngay cạnh ô lệnh.