2012-01-20 21 views
5

Tôi cần theo dõi những người dùng đang trực tuyến trên trang web của mình để tôi có thể hiển thị biểu tượng "trực tuyến" bên cạnh hình đại diện của những người dùng đang trực tuyến.Tại sao truy vấn MySQL của tôi nhanh khi tôi làm theo cách này và làm chậm khi tôi thực hiện theo cách này?

Bước đầu tiên của việc phát hiện này là để theo dõi khi người dùng đã được nhìn thấy lần cuối vì vậy tôi đang làm một truy vấn UPDATE mỗi khi người dùng yêu cầu một trang:

UPDATE `users` 
SET `last_seen` = CURRENT_TIMESTAMP 
WHERE `user_id` = '$user_id' 

Bây giờ ngay sau này, tôi thực hiện truy vấn khác, chương trình này được tất cả những người sử dụng trang web của tôi dưới tiêu chí nhất định để tôi có thể hiển thị chúng trên trang chủ:

SELECT *, 
(ACOS(SIN(0.7103989219783) * SIN(RADIANS(users.latitude)) + COS(0.7103989219783) * COS(RADIANS(users.latitude)) * COS(RADIANS(users.longitude) - -1.2894447135174)) * 6371) AS SearchRadius 
FROM `users` 
INNER JOIN `profiles` ON (
    users.user_id = profiles.user_id 
) 
WHERE (users.latitude > 38.904216788163 AND users.latitude < 42.501503211837) 
AND (users.longitude > -76.252301637251 AND users.longitude < -71.507178362749) 
AND (ACOS(SIN(0.7103989219783) * SIN(RADIANS(users.latitude)) + COS(0.7103989219783) * COS(RADIANS(users.latitude)) * COS(RADIANS(users.longitude) - -1.2894447135174)) * 6371) < 200 AND users.sex = '1' AND users.seeking = '2' AND users.user_id != '1' AND users.account_status = '1' LIMIT 0, 10 

Đừng bận tâm sự điên cuồng của truy vấn này, về cơ bản vấn đề là tôi chọn so với cùng users bảng mà trước đây tôi đã cập nhật ing.

Khi tôi thực hiện các truy vấn 2 cái khác đó là những lần tôi nhận được:

1st query: 0.0392 seconds 
2nd query: 1.5396 seconds 

Điều này gây ra một sự chậm trễ đáng kể trong thời gian tải trang.

Bây giờ khi tôi đã tạo ra một bảng riêng biệt cho người dùng trực tuyến và thay đổi các truy vấn đầu tiên này:

UPDATE `online_users` 
SET `last_seen` = CURRENT_TIMESTAMP 
WHERE `user_id` = '$user_id' 

Thời gian đã thay đổi như thế này:

1st query: 0.0411 seconds 
2nd query: 0.0008 seconds 

và trang tải nhanh hơn nhiều!

Tại sao điều này? Tôi đoán là nó có một cái gì đó để làm với khóa bàn nhưng tôi không biết đủ để chắc chắn hoặc biết thêm chi tiết.

+0

Truy vấn thứ hai vẫn trả về kết quả chính xác? –

+1

Nếu bạn chạy truy vấn thứ hai mà không có truy vấn đầu tiên thì nhanh hơn? Nó có thể là một số loại I/O vấn đề - Tôi không lên trên internals MySQL, nhưng đó không phải là loại điều đó là chặn trong ý nghĩa SQL, sau khi tất cả nó hoặc là trên cùng một kết nối trong cùng một giao dịch, trong trường hợp đó, nó được phép xem các thay đổi không được cam kết hoặc các thay đổi đã được cam kết. Bạn đang sử dụng InnoDB hay MyISAM? –

+0

@Cade Roux Nếu tôi chạy truy vấn thứ hai một mình nó nhanh hơn nhưng chỉ bằng một số tiền là 0,0004. Tôi đang sử dụng MyISAM. – TK123

Trả lời

1

SELECT * bao gồm last_seen MySQL không thể lưu trữ truy vấn hoặc truy vấn con. Bạn có thể thử liệt kê rõ ràng tất cả các trường nhưng last_seen.

(Tuy nhiên, một bảng riêng biệt online_users làm cho nhiều ý nghĩa.)

+0

vừa thử với lời gọi rõ ràng tới tất cả các tên cột ngoại trừ last_seen và thời gian truy vấn vẫn có cùng độ dài. – TK123

+0

Vì vậy, chúng tôi khôn ngoan hơn; chỉ cần cập nhật cùng một bảng xóa _all_ dữ liệu truy vấn được lưu trong bộ nhớ cache của bảng đó. Hoặc một cái gì đó che khuất như phân bổ luồng trên mỗi bảng và ghi lại bản cập nhật đĩa. –

-4

truy vấn trên bảng InnoDB là chậm hơn so với trên MyISAM. nhiều hàng trong bảng khiến truy vấn chậm hơn. lập chỉ mục sai trên bảng khiến truy vấn chậm hơn, kiểm tra bằng lệnh GIẢI THÍCH.

0

Giả sử truy vấn SELECT đang chạy nhiều lần trước khi thử nghiệm của bạn, bạn có thể thấy ảnh hưởng của bộ nhớ cache truy vấn. Mọi cập nhật trên bảng sẽ làm mất hiệu lực bộ nhớ cache và buộc truy vấn phải được thực hiện lại. Bằng cách cập nhật một bảng khác, bạn sẽ tránh được các mục nhập bộ nhớ cache.

+0

điều này có ý nghĩa, nhưng trong trường hợp của tôi, tôi có truy vấn đó chỉ thực hiện một lần và đó là sau truy vấn cập nhật. – TK123

+0

Lưu ý rằng bạn có thể xác nhận điều này bằng 'SET SESSION query_cache_type = OFF;' trước khi chạy bất kỳ lệnh nào khác. (Điều này sẽ chỉ vô hiệu hóa bộ nhớ truy vấn cho kết nối hiện tại.) –

Các vấn đề liên quan