[Help] Cấu hình MySQL xử lý >= 50M records

Discussion in 'Thảo Luận Chung' started by command, Mar 2, 2019.

  1. princenuce

    princenuce Sơ Nhập Giang Hồ

    chưa hiểu bạn muốn select như nào mà lại chậm
     
  2. Tuan

    Tuan Tân Thủ Thôn

    tốt nhất đừng count. Count với bất cứ cơ sở dữ liệu nào cũng sẽ lâu, đôi khi nhanh chỉ vì query được cache thôi. Select chỉ lấy tương đối rồi áng chừng còn records hay ko, ví dụ limit 40 nhưng nó trả về 39 là hết rồi.
     
    princenuce likes this.
  3. money

    money Hương Chủ

    Lập trình mà “áng chừng” là không ổn rồi. Còn đúng là phân trang thì không cần count nhưng count 40 nó trả về 40 thì làm sao biết đã hết hay chưa để show Next hay không? Nên giải pháp là nếu mỗi page show 40 rows thì hãy limit 41 rows, nếu trả đủ 41 thì vẫn chỉ show 40 nhưng mình biết là cần ít nhất 1 page nữa —> show Next còn ngược lại thì không show nữa.
     
    Nai, Tuan, EDM and 2 others like this.
  4. princenuce

    princenuce Sơ Nhập Giang Hồ

    dữ liệu của mình không nhất thiết phải chính xác nên đâu cần phải cứng nhắc vậy, mình cứ áng áng mà lấy ra thôi miễn là cảm thấy "phù hợp và chấp nhận được", còn nếu mình cần chia chính xác thì nên làm ngay từ đầu về để tối ưu tốc độ truy vấn và hiệu năng chứ ko phải chờ đến khi nó phình to mới tìm cách tối ưu
     
  5. money

    money Hương Chủ

    Bây giờ ví dụ nhé: làm 1 triệu tags, mỗi tag có 1 page riêng để show các data liên quan và các pages này đều phân trang. Câu hỏi đặt ra là:
    - Nếu "áng chừng", bạn sẽ show ra bao nhiêu trang cho từng tags?
    - Con số nào là "phù hợp và chấp nhận được" ? Vì sao lại chọn con số đó mà không phải con số khác?
    - Trường hợp như mình đã nói - query limit 40 nó trả đủ 40 thì làm sao biết là còn hay hết records - để không show trang kế tiếp ra? Vì nếu lỡ mà show ra 1 trang trắng nhưng mình không biết trang đó không có data và vẫn hiện ads (AdSense) thì khả năng bị banned site là có (vì mình đã bị 1 lần trên 1 site kha khá traffic)

    Trước giờ mình chỉ làm có 2 cách thôi:
    - 1 là show đúng 1 page không paging (nếu thích thì làm ajax cho load more)
    - 2 là đã paging thì phải đảm bảo paging cho đúng và hiện data chuẩn

    Nên thật sự không hiểu cách "áng chừng" như bạn nói.
     
    command likes this.
  6. princenuce

    princenuce Sơ Nhập Giang Hồ

    Tại sao ko làm chỉ có next và prev, khi next ta quẻy lấy start và limit, nếu như ko có sẽ redirect về trang trước đó,
     
  7. console

    console Bang Chúng

    Vậy thì có khác gì ajax load more hỡi người anh em thiện lành
     
  8. princenuce

    princenuce Sơ Nhập Giang Hồ

    Muốn ajax load more hay không load more thì có làm sao. Còn với cục data to như này mà di count rồi phân trang thì mình ko ý kiến gì nữa. Cám ơn.
     
  9. console

    console Bang Chúng

    Bác ấy chỉ count để thống kê chứ k phải phân trang bạn ơi. Bạn hiểu sai ý rồi. Chủ yếu là chậm quá nên muốn kiếm cách nhanh hơn ấy mà.
     
  10. money

    money Hương Chủ

    Ở trên mình đã nói là làm Next và prev rồi còn gì? Hoặc làm kiểu Ajax.
    Nhưng bạn nói “áng chừng” mới thắc mắc chứ?
     
  11. money

    money Hương Chủ

    Còn thớt cũng nói là làm next prev chứ có nói count để paging đâu?
     
  12. Tuan

    Tuan Tân Thủ Thôn

    Cái chính là ko count.
    Cách làm select 41 đưa vào bộ nhớ rồi từ bộ nhớ lấy ra 40 của money hay hơn của mình. Mặc dù xác suất trang trắng khá nhỏ 1/40 nhưng tránh hẳn trang trắng khỏi phải redirect vẫn hay hơn, công sức thì vẫn vậy, chỉ có 1 query.
     
  13. command

    command Bang Chúng

    Đó giờ chưa làm cách limit 41 mà show 40, nhưng rõ ràng cách này rất hay và tối ưu cho paging. Thanks anh Andy,
     
    Hoa Mãn Lâu likes this.
  14. Nai

    Nai MiddleMan Staff Member

    Không ngờ có kiểu nghĩ lạ đời như vậy. Thường count dữ liệu lâu quá mà em muốn tăng thêm data cho bot đọc thì 1 page cat show cả đống phân trang. Trang nào ko có data thì redirect về trang 1 =.=.
    Vote 5 * cho idea
     
  15. Kiến Lửa

    Kiến Lửa Tân Thủ Thôn

    1. count(1) -> sẽ đọc qua tất cả các record nên sẽ rất lâu.
    2. offset 9999 -> sẽ đọc đến record 9999 nên cũng sẽ rất lâu.

    Vậy add thêm column "row_num" vào và index, giá trị tăng dần.
    SELECT <fields> FROM <table> ORDER BY id DESC limit 10 offset 0;
    -->
    SELECT <fields> FROM <table> WHERE row_num > 500 and row_num < 550 ORDER BY id;

    Lúc này câu query chỉ đọc 50 record thôi.
     
  16. Nai

    Nai MiddleMan Staff Member

    Column "row_num" mà cụ add vào khác gì với cột id? khi cũng được index và cũng giá trị tăng dần mặc định như cột id
     
  17. Kiến Lửa

    Kiến Lửa Tân Thủ Thôn

    Nếu cột id bác có data kiểu vậy thì dùng luôn. Khỏi add

    Ngoài ra thì select count(1) --> select max(id) luôn
     
    Nai likes this.
  18. Nai

    Nai MiddleMan Staff Member

    Mấy web có data hàng triệu rows thì dùng lệch gì select cho nhanh đây cụ.
    Dạng select pro_id from cat_pro where cat_id = <cat_id> limit <start>,<limit> ấy. Càng về sau thấy càng chậm. Tuy có cache cho đợt đầu rồi nhưng phát đầu tiên vẫn chậm đến mức được ghi vào cả slow log
     
  19. Kiến Lửa

    Kiến Lửa Tân Thủ Thôn

    schema ra sao bác?
    Đang hiểu có table cat_pro có column (cat_it, pro_id) là KEY
    Và query lấy ra 10 product trong cate nào đó.
    Đoán là khi query [where cat_id = <cat_id>] ra quá nhiều record nên chậm
    Nên vẫn theo cách trên là [where cat_id = <cat_id> and pro_id > 0 and pro_id < 10]
    Lưu ý, pro_id lúc này data không tăng dần đc thì phải add column như trên
     
  20. Nai

    Nai MiddleMan Staff Member

    Table thế này đây cụ
    upload_2019-6-18_21-24-11.png
    lúc query em chỉ có cat_id thôi, và cần là cần product_id để phân trang.
    Nên query phải có limit mà data hiện tại theo câu lệnh explain select count(*) thì tầm 33m rows nên mấy trang đầu thì ok, về cuối trang thì query tầm 4s nên khá là chậm