Lấy nhanh random rows trong mysql table

Discussion in 'Hỏi Đáp Kỹ Thuật' started by Trí Mén, Oct 3, 2017.

  1. Trí Mén

    Trí Mén Moderator Staff Member

    Em có db mysql tầm chục M rows. Giờ em muốn select ngẫu nhiêu 1M rows, nhưng xài order by rand() thì quá chậm. Thêm nữa là e ko đánh số thứ tự cho rows nên select theo kiểu random ID ko được.
    Có cách nào giải quyết ko mấy thánh?
     
  2. Dung Vuong

    Dung Vuong Sơ Nhập Giang Hồ

    Bác dùng câu lệnh BETWEEN nhé. Random ID và dùng BETWEEN là xong. Nhanh vô đối @@. order by rand() thì siêu chậm
     
    Trí Mén likes this.
  3. TNA90

    TNA90 Sơ Nhập Giang Hồ

    mình vẫn dùng OFFSET + LIMIT. Cơ mà chưa thử lấy 1 phát 1 triệu dòng bao giờ :-ss
    OFFSET nó sẽ bỏ qua một lượng dòng nhất định đầu tiên do mình chỉ định và chỉ tính từ dòng tiếp theo.
    Làm biến $offset=rand(0,tổng số row -1) rồi quất là ok + thêm LIMIT để giới hạn số dòng cần lấy.
     
    Trí Mén likes this.
  4. console

    console Bang Chúng

    Between nó chỉ lấy khoảng id thì cũng chưa random lắm. Hóng cao nhân {big_smile}
     
    Trí Mén likes this.
  5. Trí Mén

    Trí Mén Moderator Staff Member

    db em ko có id để xài between thím ơi
    Cách của bác chưa giải quyết đc triệt để nhưng xài tạm cũng dc :D
     
  6. money

    money Hương Chủ

    Sao ko chịu làm id vậy thớt? Table mà ko có field PK kiểu id sẽ chậm hơn và khi order thỉnh thoảng nó ko chính xác.
     
  7. EDM

    EDM Sơ Nhập Giang Hồ

    E có đánh số id nhưng mà id nó liền nhau thì sao ạ? Dạng như 1,2,100,101. Vẫn đang hóng cách random nhanh :D
     
  8. money

    money Hương Chủ

    ID auto increment với step = 1 thì liền nhau vậy đó.
    Random theo ID thì sinh ra ngẫu nhiên N số lưu vào 1 string randomString theo dạng (n1, n2, n3) rồi dùng câu lệnh: select field1, field2 from table where id in randomString
     
    EDM and Trí Mén like this.
  9. Trí Mén

    Trí Mén Moderator Staff Member

    Em đang crawl rồi insert ignore vào, lỗi hoặc trùng thì nó sẽ nhảy cái id của e. Còn 1 cách là đợi nào crawl xong thì e đánh số laị từ đầu luô
     
  10. EDM

    EDM Sơ Nhập Giang Hồ

    Hi sorry anh sáng e gõ điện thoại mắt mờ quá nên nhầm, id của e vẫn increment nhưng mà không liên nhau đó anh :D, nếu vậy có cách nào mình cho id tự liền nhau không anh? Từ 1 2 23 50 100... trở về 1 2 3 4...100
     
  11. money

    money Hương Chủ

    Vậy vấn đề là 2 bé sợ id ko liền nhau khi query lên nó thiếu à?
    Anh vẫn làm là: nếu cần random 100 rows thì anh sẽ random 150 số giữa min id và max id. Sau đó query như ở trên và limit 100.
     
    EDM likes this.
  12. automan

    automan Hương Chủ

    Thánh Trí xem tham khảo cái này nhé :D

    https://pastebin.com/qn3Dj7uF

    Bao tỷ row cũng không chậm, vẫn random item :D

    Em toàn dùng thế này {big_smile}
     
    Vito_King and Trí Mén like this.
  13. dinhthangbkvn

    dinhthangbkvn Khách Qua Đường

    Cách này chỉ chuẩn khi id được lưu liên tiếp. Nếu lỗ chỗ thì phải query rất nhiều lần. Yêu cầu lấy random 1M records trong 2M records của bác Trí có vẻ không thực tế lắm, thông thường em thấy mọi người hay lấy random vài chục record để hiển thị trên 1 trang nào đó. Đây là cách làm của em:

    SELECT * FROM
    (SELECT ID FROM PRODUCTS ORDER BY RAND() LIMIT 10) A
    INNER JOIN PRODUCTS B on B.ID = A.ID;

    Trong đó ID là PK. Sẽ nhanh hơn rất nhiều so với SELECT * FROM PRODUCTS ORDER BY RAND() LIMIT 10
     
    automan likes this.
  14. automan

    automan Hương Chủ

    uhm nếu ip nhảy step nhiều thì nên xài cách khác :D
     
    Trí Mén likes this.
  15. money

    money Hương Chủ

    Không ăn thua nếu DB lớn tầm chục M rows. Cỡ 2-3 M rows là câu lệnh SELECT ID FROM PRODUCTS ORDER BY RAND() LIMIT 10 đã chậm rồi, có khi mất 1-2s mới xong.
     
  16. dinhthangbkvn

    dinhthangbkvn Khách Qua Đường

    Đúng rồi bác. Tất nhiên mình nên tùy biến theo yêu cầu để đạt mục đích. Mục đích là mỗi lần vào hiển thị ngẫu nhiên một số bài viết lên trang, vậy thay vì random trong cả DB thì mình có thể random theo từng category. Mỗi category chắc tầm vài chục K đến trăm K là cùng. :D
     
    Trí Mén likes this.
  17. Lê Tuấn

    Lê Tuấn Tân Thủ Thôn

    Bác chạy mysql trên windows hay linux thế bác?
     
  18. Trí Mén

    Trí Mén Moderator Staff Member

    Túm lại test sáng h e thấy cách của a @money là khả thi nhất, nhưng tốt nhất vẫn là đánh id lại khi crawl xong.

    chạy trên linux bác ơi
     
    Lê Tuấn likes this.
  19. money

    money Hương Chủ

    Đánh lại id cho DB lớn chậm lắm em. Đến 1 lúc Db đủ to thì chỉ sửa 1 cái bé xíu cũng không muốn làm :D
     
  20. automan

    automan Hương Chủ

    db to nhất của anh khoảng bao nhiêu Te-ra-bai :D

    db em toàn vài tram Mb là phổ biến, lớn nhất thì tầm 15Gb :D