Asked Mar 12th, 11:48 a.m. 262 1 4
  • 262 1 4
+1

Tăng hiệu năng khi truy vấn sql trong laravel

Share
  • 262 1 4

$countPost = DB::table('posts')->whereIn('id', $arr)->count();

Mình có 1 câu truy vấn như trên. Vấn đề xảy ra khi mảng $arr nó lớn ( rất lớn ) thì nó cho kết quả $countPost =0 . Cụ thể dữ liệu hiện tại của mình có tầm 37.000 bản ghi và mảng $arr thì tầm khoảng 30.000 ID. và hệ thống không count được. Xin giúp đỡ.

4 ANSWERS


Answered Mar 14th, 3:05 a.m.
+2

The number of values in the IN list is only limited by the max_allowed_packet value.

Mình nghĩ đoạn này bạn có thể có 2 cách giải quyết

  1. Sử dụng hàm chunk trong Laravel để giới hạn bản ghi cần
  2. Còn một cách thủ công nữa bạn có thể thử là set cái max_allowed_packet tăng size nó lên (https://stackoverflow.com/questions/8062496/how-to-change-max-allowed-packet-size)
Share
Avatar LongThanh @LongThanh.it
Mar 15th, 4:42 a.m.

cách thứ 2 có vẻ là đúng cái mình cần. thanks

0
| Reply
Share
Answered Mar 14th, 10:33 a.m.
+2

theo mình chia mảng arr thành nhiều mảng con, rồi count từng cái sau đó cộng lại, đk mảng arr phải làm sạch trước khi chia, tức là ko có id trùng nhau

Share
Answered Mar 14th, 3:02 a.m.
+1

sao ko dùng count($arr) có phải nhanh hơn ko :v

Share
Avatar CongHD @conghdql4
Mar 14th, 5:13 a.m.

Trường hợp item có trong $arr nhưng không có trong CSDL thì sai rồi bạn

0
| Reply
Share
Avatar Lê Vĩnh Thiện @le.vinh.thien
Mar 14th, 6:33 a.m.

@conghdql4 vậy thì bạn sai từ cái đoạn lấy ra cái $arr. tại sao lại xuất hiện những ID ko tồn tại, rồi để phải xử lý sql khổ như vậy.

0
| Reply
Share
Avatar CongHD @conghdql4
Mar 14th, 7:34 a.m.

@le.vinh.thien Ví dụ như chủ thớt muốn đếm những account đều xuất hiện ở hệ thống A và hệ thống B thì sao bạn ?

+1
| Reply
Share
Avatar CongHD @conghdql4
Mar 14th, 7:34 a.m.

@le.vinh.thien Về cơ bản, 1 website có thể trích xuất dữ liệu từ nhiều CSDL 1 lúc.

+1
| Reply
Share
Avatar Phong @zhujinfeng
Mar 14th, 3:13 p.m.

Bạn ấy đang muốn xử lý ở db mà bạn? Dùng hàm count như thế thì nó load 30k items lên memory thì chết mất.

+1
| Reply
Share
Avatar LongThanh @LongThanh.it
Mar 15th, 4:41 a.m.

Đúng rồi mình không count vậy được. Bài toán của mình như này. Mình phải lấy 1 mảng cực to sau đó vì đặc thù mảng đó sẽ phải trừ đi Mảng A, trừ mảng B nữa sau đó mới ra được cái $arr như trên. Câu truy vấn dưới đây là mình tóm lại thôi chứ thực ra yêu cầu là cần đếm số post trong cái mảng $arr kia và có date > mốc thời gian .

$countPost = DB::table('posts')->whereIn('id', $arr)->count();

Vì thế k dùng count($arr) được. vì cái size của $arr to nên truy vấn nó bị limit gì đó nên cout chắc là ko chạy đc hết nên nó return về 0.

0
| Reply
Share
Avatar Lê Vĩnh Thiện @le.vinh.thien
Mar 15th, 7:48 a.m.

@LongThanh.it vậy thì bài toán của b phải làm lại từ chỗ lấy mảng to, trừ A, B kia. chứ ko phải tìm cách để bypass cái whereIn để nó xử lý đc nhiều hơn vì hãy nghĩ đến dữ liệu có 100k, 1tr thì tăng cái max_allowed_packet đến bao giờ cho đủ. ví dụ mảng $arr chứa 30k posts rồi thì ko cần dùng sql để đếm số post có date > mốc thời gian nữa. có thể dùng for để lặp rồi đếm or đơn giản hơn là khi lấy ra mảng cực to, mảng A, mảng B thì lấy những cái có date phù hợp trc đã.

@conghdql4 Ví dụ như chủ thớt muốn đếm những account đều xuất hiện ở hệ thống A và hệ thống B thì sao bạn ?

ví dụ gặp trg hợp ntn thì nên có 1 bảng riêng để lưu thông tin rằng account ở A có tồn tại ở B ko và ngược lại. việc check này đc thực hiện sau khi đk tài khoản. sau đó việc count và thống kê dễ dàng hơn rất nhiều. ví dụ FB check xem user có dùng Insta ko thì chẳng nhẽ mỗi lần check lại whereIn với hàng triệu , hàng tỷ ID.

+1
| Reply
Share
Answered Mar 22nd, 2:49 a.m.
+1

nếu cái $arr bạn lấy từ 1 table khác thì cách tốt nhất là bạn join 2 bảng và count()

Share
Viblo
Let's register a Viblo Account to get more interesting posts.