Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Ý nghĩa về hiệu suất của việc cho phép sử dụng bí danh trong mệnh đề HAVING

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

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cấu trúc cơ sở dữ liệu Drupal - Hiệu quả / Không hiệu quả?

  2. Lỗi nhập MySQLdb trong Python - Mac 10.6

  3. Kết nối với mysql trên một máy chủ khác

  4. truy vấn cực kỳ chậm sau khi chuyển sang mysql 5.7

  5. Giải thích về MySQL Single Quotes, Double Quotes, Back Quotes Cách sử dụng