Trang 1 / 3 123 LastLast
Hiển thị kết quả từ 1 đến 10 / 26
  1. #1
    Tham gia
    06-05-2008
    Location
    tân an
    Bài viết
    226
    Like
    0
    Thanked 23 Times in 12 Posts

    Giúp đỡ tối ưu MySQL Query

    mình gặp 1 bài toán truy vấn mysql SQL sau:

    lấy 3 row kế tiếp trong csdl
    vd đánh chỉ số 1 2 3 4 5

    chọn 4 thì lấy row 5 1 2
    chọn 5 thì 1 2 3
    chọn 2 thì 3 4 5

    hiện tại mình đã giải quyết dc vấn đề nhưng code dài đến 4 dòng, chứa đến 4 COUNT(*) vậy ae nào gặp phải trường hợp này có cách nào giải tốt hơn mà ko dùng đến PHP thì giúp mình với. xin cám ơn
    Quote Quote

  2. #2
    Tham gia
    14-12-2008
    Bài viết
    1,343
    Like
    16
    Thanked 10 Times in 10 Posts
    gọi số chọn là A

    1.query 1 : select id from table where id > a order by id asc limit 3

    2.count(result) lấy ra số dữ liệu còn thiếu B

    3. query 2 : select id from table order by id asc limit B

    4. ghép 2 mảng lại.

    tối ưu hay ko còn phụ thuộc vào khung cảnh thực tế, tạm thời mình chỉ nghĩ simple là zị.

  3. #3
    Tham gia
    03-02-2009
    Bài viết
    1,192
    Like
    0
    Thanked 1 Time in 1 Post
    Code:
    $sql="(SELECT * FROM table WHERE id>4) UNION (SELECT * FROM table LIMIT 0,3) LIMIT 0,3";
    Được sửa bởi thuyduongcd lúc 10:59 ngày 04-04-2011

  4. #4
    Tham gia
    25-03-2008
    Bài viết
    235
    Like
    0
    Thanked 2 Times in 2 Posts
    Quote Được gửi bởi diepnghitinh View Post
    mình gặp 1 bài toán truy vấn mysql SQL sau:

    lấy 3 row kế tiếp trong csdl
    vd đánh chỉ số 1 2 3 4 5

    chọn 4 thì lấy row 5 1 2
    chọn 5 thì 1 2 3
    chọn 2 thì 3 4 5

    hiện tại mình đã giải quyết dc vấn đề nhưng code dài đến 4 dòng, chứa đến 4 COUNT(*) vậy ae nào gặp phải trường hợp này có cách nào giải tốt hơn mà ko dùng đến PHP thì giúp mình với. xin cám ơn
    Thử nghĩ đến việc Union all bảng gốc với n (n=3) phần từ đầu tiên của bảng này xem. SQL server thì mình đã từng làm nhưng MySql mình ko biết nên ko biết viết lệnh cụ thể như thế nào

  5. #5
    Tham gia
    06-05-2008
    Location
    tân an
    Bài viết
    226
    Like
    0
    Thanked 23 Times in 12 Posts
    Quote Được gửi bởi thuyduongcd View Post
    Code:
    $sql="(SELECT * FROM table WHERE id>4) UNION (SELECT * FROM table LIMIT 0,3) LIMIT 0,3";
    cám ơn bạn, code của bạn đã giải quyết vấn đề sắp xếp theo ASC
    Còn trong vấn đề của mình là DESC và đây là table của mình


    item_id item_catid
    1-------8
    2-------8
    3-------8
    4-------8
    5-------8
    7-------10

    _ khi mà chọn item_id 4 thì show ra các record có item_id là 3 2 1
    _ khi chọn item_id 2 thì show ra các record có item_id là 1 5 4
    _ item_id=1 thì show ra các record có item_id là 5 4 3

    vậy code sau của mình ko tối ưu chỗ nào vậy các bạn
    PHP Code:
    $item_id 2;
    $item_catid 8;
    $limit 3
    (SELECT * FROM ((SELECT * FROM shop_product_item ORDER BY item_id DESC) as tb1)
    WHERE
    item_id < $item_id AND item_catid = $item_catid
    ORDER BY item_id DESC)

    UNION

    (SELECT * FROM ((SELECT * FROM shop_product_item ORDER BY item_id DESC) as tb1)
    WHERE
    item_catid = $item_catid LIMIT 0,$limit)

    LIMIT 0,$limit

  6. #6
    Tham gia
    29-09-2005
    Bài viết
    741
    Like
    14
    Thanked 27 Times in 17 Posts
    Làm như cách của bạn ngoc_viet08 (tối đa 2 query) là tốt rồi - nếu bạn muốn DESC thì chỉ việc thay ASC bằng DESC và id < X. Nhiều bạn lầm tưởng rằng việc tối ưu hóa query đồng nghĩa với việc giảm số query. Thực tế việc tối ưu hóa bao gồm việc đảm bảo rằng các query của mình sử dụng index khi so sánh hay sort, giảm thiểu số rows mà db sẽ phải scan để trả về kết quả, tránh dùng join query khi mình không hiểu rõ những gì mà nó thực hiện, và cuối cùng mới là giảm số query tới csdl. Những query đơn giản (ko có join) và dựa trên index được thực hiện rất nhanh - và đó chính là lý do mà nhiều website có dữ liệu hàng chục triệu row mà họ vẫn sử dụng mysql một cách hiệu quả, trong khi đó nhiều website chỉ có vài trăm nghìn row nhưng vì dùng những query phức tạp (join, union là nhân tố chính trong những query này) nên performance kém. Nếu muốn đi sâu vào tối ưu hóa mysql thì cái cơ bản nhất bạn phải biết sử dụng là câu lệnh EXPLAIN và hiểu k/q nó trả về.

    Quote Được gửi bởi thuyduongcd View Post
    Code:
    $sql="(SELECT * FROM table WHERE id>4) UNION (SELECT * FROM table LIMIT 0,3) LIMIT 0,3";
    Nếu table có tương đối ít row thì có thể dùng cái này, nhưng khi số row càng nhiều thì performance sẽ càng giảm. Vì vế đầu trong query này sẽ đọc tất cả các row có id > X (X=4 trong trg hợp trên). Nếu table có nhiều row nhưng X là id của một row gần cuối table thì ko sao, vì số row phải đọc cũng ko nhiều. Nhưng nếu X là id của một row ở đầu table thì lại khác. Vừa thử chạy query trên ("(SELECT * FROM table WHERE id>4) UNION (SELECT * FROM table LIMIT 0,3) LIMIT 0,3") với 1 table > 80.000 row, câu lệnh mất hơn 3 giây để hoàn tất (& trả về 3 row k/q). Trong khi đó tổng thời gian thực hiện 2 câu lệnh sau trên cùng table chỉ mất hơn 1 ms:
    1) lấy 3 row có id > X
    2) lấy nốt 1 or 2 row ở đầu bản NẾU câu lệnh 1) ko trả về đủ 3 row

    Điều quan trọng nhất tôi muốn nói ở đây là khi optimize query bạn phải hiểu rõ cách mà csdl sẽ thực hiện từng câu lệnh của bạn. Thà dùng nhiều câu lệnh đơn giản mà bạn hiểu còn hơn dùng ít câu lệnh mà bạn ko hiểu rõ. Bởi performance của chúng có thể tốt lúc này, nhưng khi db lớn hơn thì performance lại degrade.


    Quay lại câu lệnh "(SELECT * FROM table WHERE id>4) UNION (SELECT * FROM table LIMIT 0,3) LIMIT 0,3" - khi hiểu rõ vấn đề, bạn chỉ cần thêm LIMIT 3 vào vế đầu thì câu lệnh này cũng sẽ đc optimize (chạy hiệu quả & performance ko degrade over time)!
    Được sửa bởi VnVision lúc 22:14 ngày 04-04-2011

  7. #7
    Tham gia
    25-03-2008
    Bài viết
    235
    Like
    0
    Thanked 2 Times in 2 Posts
    Uh - bổ sung thêm cho các bạn nữa là câu lệnh"(SELECT * FROM table WHERE id>4) UNION (SELECT * FROM table LIMIT 0,3) LIMIT 0,3" sẽ không đúng khi trường ID ko phải là auto increment (tức là cần phải bổ sung order by thì mới đúng)

  8. #8
    Tham gia
    03-02-2009
    Bài viết
    1,192
    Like
    0
    Thanked 1 Time in 1 Post
    Tôi chỉ cho bạn con đường còn đi thế nào là tự bạn. Tôi không đủ thời gian để "ẵm" bạn đến đích rồi thả xuống đúng chỗ cần. Làm như vậy khác nào phế đôi chân của bạn đi.

    Tất cả những câu lệnh tôi đưa ra không bao giờ tròn trịa đến mức có thể "plug and play" cả (thậm chí có khi còn sai cả cú pháp). Cho nên việc performance hay optimize gì tôi chả quan tâm, mục đích chính của câu trả lời là hướng người hỏi đến từ khóa UNION. Nếu hiểu ý nghĩa nó rồi thì việc "điều khiển" nó theo ý mình là không có gì khó. Còn nếu cứ bê nguyên xi vào sử dụng mà không hiểu thì thà đừng sử dụng còn hơn.

    Và tôi cũng không nghĩ UNION 2 câu query sẽ performance kém hơn việc gọi 2 câu query riêng lẻ. Vấn đề là câu query như thế nào mà thôi.

  9. #9
    Tham gia
    29-09-2005
    Bài viết
    741
    Like
    14
    Thanked 27 Times in 17 Posts
    Quote Được gửi bởi thuyduongcd View Post
    Tất cả những câu lệnh tôi đưa ra không bao giờ tròn trịa đến mức có thể "plug and play" cả (thậm chí có khi còn sai cả cú pháp). Cho nên việc performance hay optimize gì tôi chả quan tâm, mục đích chính của câu trả lời là hướng người hỏi đến từ khóa UNION.
    Vấn đề là chủ đề này hỏi về việc làm sao để "tối ưu hoá" 1 nhiệm vụ cụ thể, nên bạn ko thể nói ko quan tâm đến performance hay optimize đc (đó là vấn đề mà chủ thớt đang quan tâm hàng đầu). Và mấu chốt trong việc tối ưu hóa ở đây không phải là việc giảm số lượng query với UNION. Bởi vậy câu trả lời của bạn không hướng người dùng đến đúng điều quan trọng nhất, mà lại đề cao một cái thứ yếu (trong trường hợp cụ thể này).

  10. #10
    Tham gia
    07-09-2006
    Bài viết
    295
    Like
    0
    Thanked 2 Times in 2 Posts
    cũng không hẳn là UNION tốc độ sẽ chậm hơn nếu bảng của bạn có khoảng vài ngàn records thì không si nhê gì cả còn nếu lớn quá lớn thì nên tìm solution khác. Vì cách của NgocViet dù gì cũng 2 lần SELECT.

Trang 1 / 3 123 LastLast

Bookmarks

Quy định

  • Bạn không thể tạo chủ đề mới
  • Bạn không thể trả lời bài viết
  • Bạn không thể gửi file đính kèm
  • Bạn không thể sửa bài viết của mình
  •