REINDEX có nguy hiểm không?


17

Tôi đã thử COUNT(*)một bảng có 150.000 hàng có khóa Chính. Nó hoạt động khoảng 5 phút, vì vậy tôi nhận ra đây là một vấn đề về lập chỉ mục.

Trích dẫn hướng dẫn sử dụng PostgreSQL :

REINDEX tương tự như việc thả và tạo lại chỉ mục trong đó nội dung chỉ mục được xây dựng lại từ đầu. Tuy nhiên, các cân nhắc khóa là khá khác nhau. REINDEX khóa ghi nhưng không đọc bảng cha của chỉ mục. Nó cũng có một khóa độc quyền trên chỉ mục cụ thể đang được xử lý, nó sẽ chặn các lần đọc cố gắng sử dụng chỉ mục đó (...) CREATE INDEX tiếp theo khóa ghi nhưng không đọc; vì chỉ mục không có ở đó, không đọc sẽ cố gắng sử dụng nó, có nghĩa là sẽ không có chặn nhưng đọc có thể bị buộc phải quét liên tục đắt tiền.

Từ kinh nghiệm của bản thân, bạn có thể nói:

  • REINDEXINGnguy hiểm không Nó có thể làm hại tính nhất quán dữ liệu?
  • Nó có thể mất rất nhiều thời gian?
  • Nó có phải là một giải pháp có thể xảy ra cho kịch bản của tôi?

Cập nhật:

Giải pháp hiệu quả với chúng tôi là tạo lại cùng một chỉ mục với một tên khác, sau đó xóa chỉ mục cũ.

Việc tạo chỉ mục rất nhanh và chúng tôi đã giảm kích thước chỉ mục từ 650 MB xuống còn 8 MB. Sử dụng COUNT(*)với betweenchỉ mất 3 giây.

Câu trả lời:


15

Reindexing không nguy hiểm và không thể gây hại cho tính nhất quán của dữ liệu. Tuy nhiên, nếu bạn có thời gian ghi quan trọng, bạn có thể mất dữ liệu nếu bảng bị khóa và DML bị hủy bỏ.

Reindexing không nên mất nhiều thời gian, nhưng thường sẽ bao gồm việc đọc toàn bộ bảng, sắp xếp các trường chỉ mục và viết một chỉ mục mới. Cho thời gian cho COUNT(*)nó có thể sẽ mất năm phút trở lên.

Đây không phải là một vấn đề lập chỉ mục. COUNT(*)nên sử dụng quét bảng trong trường hợp không đọc chỉ mục. Tôi hy vọng bạn có một vấn đề IO nào đó.

Hãy thử sử dụng COUNT(1)hoặc COUNT(pk_field)có thể sử dụng chỉ mục.

Nếu bạn đang chạy trên nền tảng Unix hoặc Linux, bạn có thể muốn theo dõi hoạt động của đĩa sar. Bạn cũng có thể có một đĩa bị lỗi có thể làm giảm đáng kể tốc độ IO.

Các bảng có đối tượng lớn cũng có thể tăng IO đáng kể để tạo các bản ghi cho COUNT (*).


2
Theo wiki.postgresql.org, COUNT(*)là lựa chọn tốt nhất:If you are using count(*), the database is free to use any column to count, which means it can pick the smallest covering index to scan (note that this is why count(*) is much better than count(some_field), as long as you don't care if null values of some_field are counted). Since indexes often fit entirely in memory, this means count(*) is often very fast.
cam80

1

Tôi không chắc câu trả lời tốt nhất cho bạn. Tuy nhiên, chủ đề này dường như cung cấp một số đề xuất tốt: n http://postgresql.1045698.n5.nabble.com/count-performance-su-td2067873.html

Một lưu ý là bạn có thể triển khai TRIGGER để duy trì số lượng hàng trong một bảng riêng biệt (nếu COUNT (*) sẽ được các ứng dụng của bạn gọi thường xuyên).

Một số câu trả lời cho rằng đây là triệu chứng của cơ sở dữ liệu chưa được hút bụi gần đây (gợi ý rằng tính năng tự động bị vô hiệu hóa trên máy chủ của bạn hoặc cụ thể là cho cơ sở dữ liệu đó)?

Một đề nghị khác trông giống như:

ANALYZE tablename;
SELECT reltuple FROM pg_class WHERE relname = 'tablename';

Và ai đó được xác định là A. Kretschmer ghi chú:

Không. Việc thực hiện chỉ mục hiện tại không chứa thông tin về khả năng hiển thị hàng trong giao dịch hiện tại. Bạn cần quét toàn bộ bảng dữ liệu để lấy nếu hàng hiện tại hiển thị trong giao dịch hiện tại.

... ủng hộ nhận xét của tôi về quyền cấp hàng là mối quan tâm về hiệu suất.

Tìm kiếm của tôi cũng bật lên WikiVS: MySQL so với PostgreSQL: COUNT (*) .

Bạn có thể kiểm tra các kết quả khác mà tôi đã tìm thấy bằng cách sử dụng Google: hiệu suất đếm postgresql (*)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.