Nur auf diese bestimmte Abfrage konzentriert, und mit Beispieldaten unten geladen. Dies adressiert einige andere Abfragen wie die von anderen erwähnte count(distinct ...)
.
Die alias in the HAVING
scheint entweder ihre Leistung etwas zu übertreffen oder ihre Leistung (je nach Abfrage) deutlich zu übertreffen.
Dies verwendet eine bereits existierende Tabelle mit etwa 5 Millionen Zeilen darin erstellt schnell über diese answer von mir, die 3 bis 5 Minuten dauert.
Resultierende Struktur:
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;
Aber statt mit INNODB. Erstellt die erwartete INNODB-Lückenanomalie aufgrund der Bereichsreservierungseinfügungen. Nur zu sagen, macht aber keinen Unterschied. 4,7 Millionen Zeilen.
Ändern Sie die Tabelle, um Tims angenommenem Schema zu nähern.
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
Das folgende wird eine Weile dauern. Führen Sie es immer wieder in Chunks aus, sonst könnte die Verbindung zu einem Timeout führen. Die Zeitüberschreitung ist auf 5 Millionen Zeilen ohne eine LIMIT-Klausel in der Update-Anweisung zurückzuführen. Beachten Sie, wir do haben eine LIMIT-Klausel.
Wir machen es also in einer halben Million Iterationen. Setzt eine Spalte auf eine Zufallszahl zwischen 1 und 20
update students set camId=floor(rand()*20+1) where camId is null limit 500000; -- well that took a while (no surprise)
Halten Sie die oben laufen, bis keine camId
null ist.
Ich lief es wie 10-mal (das Ganze dauert 7 bis 10 Minuten)
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
erstellen nützlichen Index (nach den Einsätzen natürlich).
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
Erstellen Sie die Campus-Tabelle.
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
Führen Sie die zwei Abfragen:
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
und
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
So sind die Zeiten identisch. Lief jedes ein Dutzend Mal.
Der EXPLAIN
Ausgang ist das gleiche für beide
+----+-------------+----------+------+---------------+------------+---------+----------------------+--------+---------------------------------+
| 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 |
+----+-------------+----------+------+---------------+------------+---------+----------------------+--------+---------------------------------+
Verwenden der AVG() Funktion, ich bin immer um eine 12% ige Erhöhung der Leistung mit der Alias in den having
(mit identischem EXPLAIN
Ausgang) aus dem nach zwei Abfragen.
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
Und schließlich die 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
Die Alias in dem having läuft konsequent 35% schneller mit dem gleichen EXPLAIN
Ausgang. Unten gesehen. Der gleiche Explain-Ausgang wurde zweimal angezeigt, um nicht die gleiche Leistung zu erbringen, sondern als allgemeiner Hinweis.
+----+-------------+----------+-------+---------------+------------+---------+----------------------+--------+----------------------------------------------+
| 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 |
+----+-------------+----------+-------+---------------+------------+---------+----------------------+--------+----------------------------------------------+
Der Optimizer erscheint der Alias in der mit im Moment zu begünstigen, vor allem für die DISTINCT.
ich einen Narren aus mir die ganze Zeit machen. – Drew
Mögliches Duplikat von [Eine SQL IN-Klausel parametrieren] (http://stackoverflow.com/questions/337704/parameterize-an-sql-in-clause) –