PDA

View Full Version : Giảm thời gian truy vấn dữ liệu?



langtusitinh225
05-02-2010, 14:00
Bình thường mình thường dùng câu lệnh SQL:


$sql = "select record1, record2, ... from table where ....";


Với trường hợp có quá nhiều record (rất lớn) thì thời gian select sẽ lâu hơn, vậy có những cách nào để giảm thiểu tối đa thời gian thực hiện? (về câu lệnh lẫn cấu trúc dữ liệu)
Cám ơn.

thuyduongcd
05-02-2010, 14:23
đã là câu lệnh thì làm sao mà khác đi được.
Chỉ có thể thêm LIMIT vào để lấy một số record cần thiết thôi. Không ai xử lý vài ngàn record một lúc cả

lucky-boy
05-02-2010, 14:46
Lúc thiết kế DB bạn nên chú ý đánh index các trường cần thiết thì khi select sẽ query nhanh hơn.

langtusitinh225
05-02-2010, 17:32
đã là câu lệnh thì làm sao mà khác đi được.

Có những cách biến hóa câu lệnh để làm cho chương trinh tốt hơn mà bạn.



Không ai xử lý vài ngàn record một lúc cả


Ý mình là mình chọn ra 1 số record từ rất nhiều record thì thời gian sẽ lâu hơn



Lúc thiết kế DB bạn nên chú ý đánh index các trường cần thiết thì khi select sẽ query nhanh hơn.


Không hiểu ý bạn lắm :D

haindse
05-02-2010, 20:39
Một nguyên tắc là bắt buộc phải dùng LIMIT để hạn chế số bản ghi cần lấy ra khi duyệt. Nếu ko có LIMIT thì có nghĩa là tất cả các bản ghi. Không bao giờ có nhu cầu lấy ra một lúc hàng trăm bản ghi để xử lí cả. Nếu có thì phải xem lại thuật toán.

langtusitinh225
05-02-2010, 22:37
Hic đâu có nói lấy ra hàng trăm bản ghi đâu trời.
Một ví dụ: mình có 100 record và cần lấy 10 record với mình có 10000 và cần lấy 10 record thì tốc độ khác nhau. Mình muốn hỏi là có cách nào tốt nhất để lấy ra 10 từ 10000 record mà có thể giảm thiểu tối đa thời gian thực thi

lee_huynh306
05-02-2010, 22:48
Hic đâu có nói lấy ra hàng trăm bản ghi đâu trời.
Một ví dụ: mình có 100 record và cần lấy 10 record với mình có 10000 và cần lấy 10 record thì tốc độ khác nhau. Mình muốn hỏi là có cách nào tốt nhất để lấy ra 10 từ 10000 record mà có thể giảm thiểu tối đa thời gian thực thi

Với lệnh SELECT và yêu cầu của bạn thì nhiệm vụ tối ưu thời gian thực thi thuộc về DB Engine chứ không phải bản thân người lập trình.

langtusitinh225
05-02-2010, 23:06
Em tìm được 1 bài viết như thế này:

Câu lệnh MySQL để lấy 1 phần tử ngẫu nhiên:


$sql = "select id from table order by rand() limit 1";


đây đúng là cách ngắn gọn nhất, nhưng nó không phải là 1 cách hay, vì với câu truy vấn này là rất chậm. Lý do là Mysql phải tạo 1 bảng tạm với tất cả kết quả và gán cho mỗi bản ghi một chỉ số thứ tự ngẫu nhiên. Sau đó kết quả được sắp xếp và trả về kết quả. Nó sẽ thực sự là một vấn đề lớn nếu dữ liệu nhiêu. Bạn có thể dùng code bên dứoi, tuy phải thêm mấy dòng nhưng nó thực sự tối ưu về mặt hiệu năng



$offset_result = mysql_query( " SELECT FLOOR(RAND() * COUNT(*)) AS `offset` FROM `table` ");
$offset_row = mysql_fetch_object( $offset_result );
$offset = $offset_row->offset;
$result = mysql_query( " SELECT * FROM `table` LIMIT $offset, 1 " );


Em chỉ tìm được thôi chứ không biết đúng hay sai nữa :D
Ai biết được những chiêu tương tự thế này giúp em với nha
Cám ơn

kenphan19
05-02-2010, 23:45
trước khi trả lời câu hỏi của bạn và mấy spamer ở trên, mình xin chú thích cho bạn vài điều.
1. Record và Field là 2 cái khác nhau, ở đây không có chuyện SELECT record1, record2 mà phải là field1, field2.
2. Dùng LIMIT là chính xác như ý bạn rồi mà bạn lại còn hỏi lung tung :D
3. Thêm Index vào mà bạn còn không biết thì chắc bạn chưa rành lắm về db engine.
Nói chung là bạn nên tìm hiểu căn bản trước rồi hãy tính đến việc optimize db. :D

thuyduongcd
06-02-2010, 00:06
Có những cách biến hóa câu lệnh để làm cho chương trinh tốt hơn mà bạn.
Câu lệnh là câu lệnh, không có chuyện biến hóa, chỉ có thuật toán xử lý câu lệnh khác nhau mà thôi.

Em chỉ tìm được thôi chứ không biết đúng hay sai nữa
Cái này chỉ lấy được 1 record ngẫu nhiên thôi. Lập trình là phải mang tính tổng quát để có thể tái sử dụng về sau. Khi lấy 1 record phải nghĩ đến khả năng sẽ lấy n record. Không thể bây giờ muốn lấy 1 record thì làm thế này, lấy 2 record thì làm thế khác.
Còn về đoạn code đó cũng chưa phải là tối ưu nhất đâu, còn có thể tối ưu hơn nữa kìa.

langtusitinh225
06-02-2010, 05:28
Không thể bây giờ muốn lấy 1 record thì làm thế này, lấy 2 record thì làm thế khác.


Mình không hiểu từ "không thể" của bạn, đó là tùy theo nhu cầu, tùy theo người lập trình thôi. Nếu có cách làm khác hiệu quả cao hơn thì tại sao lại không làm (hiệu quả ở đây bao gồm cả về tính đúng đắn, chương trình sáng sủa, thời gian thực thi,... Em chỉ nói chung không liên quan đến việc select ở topic này)
Em nghĩ topic này giờ nên bàn về việc sử dụng MySQL làm sao cho tốt thì hay hơn, mỗi người có cách làm khác nhau, thói quen khác nhau, nên thảo luận để hiểu hơn và để hiệu quả làm việc cao hơn.

bka
07-02-2010, 08:27
nói chung là tùy yêu cầu và trường hợp mà xử lý thôi. chẳng có cái quy tắc nào là chung trong này cả. nhưng khi viết code nên để ý một chút đến giảm tới mức tối đa xử lý của server. nó là vô cùng quan trọng cho một database lớn.

nói tới Rand trong mysql .



$offset_result = mysql_query( " SELECT FLOOR(RAND() * COUNT(*)) AS `offset` FROM `table` ");
$offset_row = mysql_fetch_object( $offset_result );
$offset = $offset_row->offset;
$result = mysql_query( " SELECT * FROM `table` LIMIT $offset, 1 " );


cách này bạn đã kiểm tra chưa mà phát biểu như thánh vậy .

tốt nhất là lấy rand của 1 giá trị từ 1 đến tổng các row đã tạo rồi gọi theo đó . đó mới là cách tối ưu nhất.

langtusitinh225
07-02-2010, 22:45
cách này bạn đã kiểm tra chưa mà phát biểu như thánh vậy .


Hay nhỉ, thế nào là "phát biểu như thánh" nhỉ, hình như mình đã nói đây là thộng tin mình tìm được thì phải.

thuyduongcd
08-02-2010, 10:14
Ai biết được những chiêu tương tự thế này giúp em với nha
chưa biết đúng hay sai mà đã gọi đó là "chiêu"

hoainguyenduc
08-02-2010, 10:36
Bình thường mình thường dùng câu lệnh SQL:


$sql = "select record1, record2, ... from table where ....";


Với trường hợp có quá nhiều record (rất lớn) thì thời gian select sẽ lâu hơn, vậy có những cách nào để giảm thiểu tối đa thời gian thực hiện? (về câu lệnh lẫn cấu trúc dữ liệu)
Cám ơn.

Mình chưa hiểu lắm câu hỏi của bạn! bạn muốn select nhìu field hay nhìu record.
Nếu lấy tất cả fields trong 1 bảng thì bạn dùng


$sql = "SELECT * FROM table";


Còn bạn muốn lấy vài field thì chỉ có cách là liệt kê ra.

Còn nếu lấy 1 record nào đó cố định, bạn nên đưa ra điều kiện chính xác để lấy dc record cần lấy.

Cho dù bạn có bao nhiu cách viết code để tối ưu, thì kết quả của bạn vẫn là 1 câu SQL theo cấu trúc


SELECT field,... FROM table WHERE option LIMIT offset, limit

rồi run câu SQL đó để lấy dữ liệu.
Thế sao không viết chỉ mỗi 1 câu SQL cho lẹ, vừa đỡ tốn thời gian ngồi suy nghĩ viết code, vừa lại đỡ tốn thời gian thực thi các câu lệnh, mà kết quả thì có khác gì nhau.

langtusitinh225
08-02-2010, 14:22
Mình chưa hiểu lắm câu hỏi của bạn! bạn muốn select nhìu field hay nhìu record.
Nếu lấy tất cả fields trong 1 bảng thì bạn dùng


$sql = "SELECT * FROM table";


Còn bạn muốn lấy vài field thì chỉ có cách là liệt kê ra.

Còn nếu lấy 1 record nào đó cố định, bạn nên đưa ra điều kiện chính xác để lấy dc record cần lấy.

Cho dù bạn có bao nhiu cách viết code để tối ưu, thì kết quả của bạn vẫn là 1 câu SQL theo cấu trúc


SELECT field,... FROM table WHERE option LIMIT offset, limit

rồi run câu SQL đó để lấy dữ liệu.
Thế sao không viết chỉ mỗi 1 câu SQL cho lẹ, vừa đỡ tốn thời gian ngồi suy nghĩ viết code, vừa lại đỡ tốn thời gian thực thi các câu lệnh, mà kết quả thì có khác gì nhau.

Đúng là em có nhầm là field chứ ko phải record
Nói chung thì những câu lệnh như trên em đều biết, chắc không có cài nào tốt hơn nữa đâu nhỉ
Thanks

[=========> Bổ sung bài viết <=========]

Cho em hỏi thêm là giờ nếu làm lịch sử đăng nhập hay nói chung là lịch sử gì cũng được của thành viên thì ở table user chứa thông tin tài khoản mình thêm 1 field là history ở dạng text rồi khi cần thì mình xử lý sao đó để xuất dữ liệu. Cách này có được không ạ, vì khi cập nhật cái text thì mình chỉ cần thêm vào có xíu mà phải lấy cả đống ra rồi ghép 2 chuỗi lại rồi đưa vào DB.

VD:


Login 13:15:05 20-02-2010 Time 0:15:5 | Login 20:18:04 20-02-2010 Time 02:34:11 | Login 07:03:49 21-02-2010 Time 03:01:05 | Login 20:18:04 21-02-2010 Time 04:34:45

ngoc_viet08
08-02-2010, 14:59
Cho em hỏi thêm là giờ nếu làm lịch sử đăng nhập hay nói chung là lịch sử gì cũng được của thành viên thì ở table user chứa thông tin tài khoản mình thêm 1 field là history ở dạng text rồi khi cần thì mình xử lý sao đó để xuất dữ liệu. Cách này có được không ạ, vì khi cập nhật cái text thì mình chỉ cần thêm vào có xíu mà phải lấy cả đống ra rồi ghép 2 chuỗi lại rồi đưa vào DB
table history : id , user_id , action , time ...