Chỉ tập trung vào truy vấn cụ thể đó và với dữ liệu mẫu được tải bên dưới. Điều này giải quyết một số truy vấn khác như count(distinct ...)
được đề cập bởi những người khác.
alias in the HAVING
dường như hoạt động tốt hơn một chút hoặc tốt hơn một chút so với thay thế của nó (tùy thuộc vào truy vấn).
Điều này sử dụng một bảng có sẵn với khoảng 5 triệu hàng trong đó được tạo nhanh chóng thông qua câu trả lời này của tôi, mất từ 3 đến 5 phút.
Cấu trúc kết quả:
CREATE TABLE `ratings` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`thing` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5046214 DEFAULT CHARSET=utf8;
Nhưng sử dụng INNODB để thay thế. Tạo ra sự bất thường về khoảng cách INNODB dự kiến do chèn đặt trước phạm vi. Chỉ nói, nhưng không tạo ra sự khác biệt. 4,7 triệu hàng.
Sửa đổi bảng để đến gần lược đồ giả định của Tim.
rename table ratings to students; -- not exactly instanteous (a COPY)
alter table students add column camId int; -- get it near Tim's schema
-- don't add the `camId` index yet
Phần sau sẽ mất một lúc. Chạy đi chạy lại nhiều lần nếu không kết nối của bạn có thể hết thời gian chờ. Thời gian chờ là do 5 triệu hàng không có điều khoản LIMIT trong báo cáo cập nhật. Lưu ý, chúng tôi làm có điều khoản LIMIT.
Vì vậy, chúng tôi đang thực hiện nó trong nửa triệu lần lặp hàng. Đặt một cột thành số thứ tự từ 1 đến 20
update students set camId=floor(rand()*20+1) where camId is null limit 500000; -- well that took a while (no surprise)
Tiếp tục chạy phần trên cho đến khi không có camId
là null.
Tôi đã chạy nó 10 lần (toàn bộ quá trình này mất từ 7 đến 10 phút)
select camId,count(*) from students
group by camId order by 1 ;
1 235641
2 236060
3 236249
4 235736
5 236333
6 235540
7 235870
8 236815
9 235950
10 235594
11 236504
12 236483
13 235656
14 236264
15 236050
16 236176
17 236097
18 235239
19 235556
20 234779
select count(*) from students;
-- 4.7 Million rows
Tạo một chỉ mục hữu ích (tất nhiên là sau khi chèn).
create index `ix_stu_cam` on students(camId); -- takes 45 seconds
ANALYZE TABLE students; -- update the stats: http://dev.mysql.com/doc/refman/5.7/en/analyze-table.html
-- the above is fine, takes 1 second
Tạo bảng khuôn viên.
create table campus
( camID int auto_increment primary key,
camName varchar(100) not null
);
insert campus(camName) values
('one'),('2'),('3'),('4'),('5'),
('6'),('7'),('8'),('9'),('ten'),
('etc'),('etc'),('etc'),('etc'),('etc'),
('etc'),('etc'),('etc'),('etc'),('twenty');
-- ok 20 of them
Chạy hai truy vấn:
SELECT students.camID, campus.camName, COUNT(students.id) as studentCount
FROM students
JOIN campus
ON campus.camID = students.camID
GROUP BY students.camID, campus.camName
HAVING COUNT(students.id) > 3
ORDER BY studentCount;
-- run it many many times, back to back, 5.50 seconds, 20 rows of output
và
SELECT students.camID, campus.camName, COUNT(students.id) as studentCount
FROM students
JOIN campus
ON campus.camID = students.camID
GROUP BY students.camID, campus.camName
HAVING studentCount > 3
ORDER BY studentCount;
-- run it many many times, back to back, 5.50 seconds, 20 rows of output
Vì vậy, thời gian là giống hệt nhau. Mỗi lần chạy hàng chục lần.
EXPLAIN
đầu ra giống nhau cho cả hai
+----+-------------+----------+------+---------------+------------+---------+----------------------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------------+---------+----------------------+--------+---------------------------------+
| 1 | SIMPLE | campus | ALL | PRIMARY | NULL | NULL | NULL | 20 | Using temporary; Using filesort |
| 1 | SIMPLE | students | ref | ix_stu_cam | ix_stu_cam | 5 | bigtest.campus.camID | 123766 | Using index |
+----+-------------+----------+------+---------------+------------+---------+----------------------+--------+---------------------------------+
Sử dụng hàm AVG (), tôi nhận được hiệu suất tăng khoảng 12% với bí danh trong having
(với EXPLAIN
giống hệt nhau
đầu ra) từ hai truy vấn sau.
SELECT students.camID, campus.camName, avg(students.id) as studentAvg
FROM students
JOIN campus
ON campus.camID = students.camID
GROUP BY students.camID, campus.camName
HAVING avg(students.id) > 2200000
ORDER BY students.camID;
-- avg time 7.5
explain
SELECT students.camID, campus.camName, avg(students.id) as studentAvg
FROM students
JOIN campus
ON campus.camID = students.camID
GROUP BY students.camID, campus.camName
HAVING studentAvg > 2200000
ORDER BY students.camID;
-- avg time 6.5
Và cuối cùng, DISTINCT
:
SELECT students.camID, count(distinct students.id) as studentDistinct
FROM students
JOIN campus
ON campus.camID = students.camID
GROUP BY students.camID
HAVING count(distinct students.id) > 1000000
ORDER BY students.camID; -- 10.6 10.84 12.1 11.49 10.1 9.97 10.27 11.53 9.84 9.98
-- 9.9
SELECT students.camID, count(distinct students.id) as studentDistinct
FROM students
JOIN campus
ON campus.camID = students.camID
GROUP BY students.camID
HAVING studentDistinct > 1000000
ORDER BY students.camID; -- 6.81 6.55 6.75 6.31 7.11 6.36 6.55
-- 6.45
Bí danh trong có liên tục chạy nhanh hơn 35% với cùng một EXPLAIN
đầu ra. Xem bên dưới. Vì vậy, cùng một đầu ra Giải thích đã được hiển thị hai lần để không dẫn đến hiệu suất giống nhau, nhưng là một manh mối chung.
+----+-------------+----------+-------+---------------+------------+---------+----------------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+------------+---------+----------------------+--------+----------------------------------------------+
| 1 | SIMPLE | campus | index | PRIMARY | PRIMARY | 4 | NULL | 20 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | students | ref | ix_stu_cam | ix_stu_cam | 5 | bigtest.campus.camID | 123766 | Using index |
+----+-------------+----------+-------+---------------+------------+---------+----------------------+--------+----------------------------------------------+
Trình tối ưu hóa dường như ưu tiên bí danh đang có vào lúc này, đặc biệt là đối với DISTINCT.