Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Implikasi kinerja mengizinkan alias untuk digunakan dalam klausa HAVING

Sangat terfokus hanya pada kueri tertentu, dan dengan contoh data yang dimuat di bawah ini. Ini menjawab beberapa pertanyaan lain seperti count(distinct ...) disebutkan oleh orang lain.

The alias in the HAVING tampaknya sedikit mengungguli atau sedikit mengungguli alternatifnya (bergantung pada kueri).

Ini menggunakan tabel yang sudah ada sebelumnya dengan sekitar 5 juta baris di dalamnya yang dibuat dengan cepat melalui jawaban ini milik saya yang memakan waktu 3 hingga 5 menit.

Struktur yang dihasilkan:

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;

Tetapi menggunakan INNODB sebagai gantinya. Membuat anomali celah INNODB yang diharapkan karena penyisipan rentang reservasi. Hanya mengatakan, tetapi tidak ada bedanya. 4,7 Juta baris.

Ubah tabel untuk mendekati skema yang diasumsikan 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

Berikut ini akan memakan waktu cukup lama. Jalankan lagi dan lagi dalam potongan atau koneksi Anda mungkin habis. Batas waktu ini disebabkan oleh 5 juta baris tanpa klausa LIMIT dalam pernyataan pembaruan. Perhatikan, kami melakukannya memiliki klausa LIMIT.

Jadi kami melakukannya dalam setengah juta baris iterasi. Menyetel kolom ke nomor acak antara 1 dan 20

update students set camId=floor(rand()*20+1) where camId is null limit 500000; -- well that took a while (no surprise)

Jalankan terus cara diatas sampai tidak ada camId adalah nol.

Saya menjalankannya seperti 10 kali (semuanya membutuhkan waktu 7 hingga 10 menit)

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

Buat indeks yang berguna (tentu saja setelah sisipan).

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

Buat tabel kampus.

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

Jalankan dua kueri:

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

dan

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

Jadi waktunya identik. Jalankan masing-masing selusin kali.

EXPLAIN outputnya sama untuk keduanya

+----+-------------+----------+------+---------------+------------+---------+----------------------+--------+---------------------------------+
| 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                     |
+----+-------------+----------+------+---------------+------------+---------+----------------------+--------+---------------------------------+

Dengan menggunakan fungsi AVG(), saya mendapatkan peningkatan kinerja sekitar 12% dengan alias di having (dengan EXPLAIN yang identik output) dari dua kueri berikut.

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

Dan terakhir, 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

Alias ​​​​dalam memiliki secara konsisten berjalan 35% lebih cepat dengan EXPLAIN yang sama keluaran. Terlihat di bawah. Jadi output Jelaskan yang sama telah ditampilkan dua kali untuk tidak menghasilkan kinerja yang sama, tetapi sebagai petunjuk umum.

+----+-------------+----------+-------+---------------+------------+---------+----------------------+--------+----------------------------------------------+
| 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                                  |
+----+-------------+----------+-------+---------------+------------+---------+----------------------+--------+----------------------------------------------+

Pengoptimal Tampaknya menyukai alias yang dimiliki saat ini, terutama untuk 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. Untuk apa driver jdbc org.gjt.mm.mysql.Driver?

  2. Dalam gabungan, cara mengawali semua nama kolom dengan tabel asalnya

  3. INSERT INTO ... SELECT tanpa merinci semua kolom

  4. Buat pengguna baru di MySQL dan berikan akses penuh ke satu database

  5. MySQL - KESALAHAN 1045 - Akses ditolak