Cha*_*kka 11 mysql sql inner-join
我有两张桌子; songs
48 959 281行,popular_songs
5 721 117行.
这是两个表的结构:
CREATE TABLE songs (
songId BIGINT(20) NOT NULL,
songName VARCHAR(1000) NOT NULL,
songDuration BIGINT(20) NOT NULL,
songPreview VARCHAR(1000) NOT NULL,
PRIMARY KEY (songId),
INDEX (songDuration)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8
DEFAULT COLLATE utf8_general_ci;
CREATE TABLE popular_songs (
storeFrontId BIGINT(20) NOT NULL,
genreId BIGINT(20) NOT NULL,
songId BIGINT(20) NOT NULL,
songRank INT(11) NOT NULL,
INDEX (storeFrontId),
INDEX (genreId),
INDEX (songId),
INDEX (songRank),
CONSTRAINT popular_song UNIQUE (storeFrontId, genreId, songId),
FOREIGN KEY (storeFrontId) REFERENCES storefront (storeFrontId),
FOREIGN KEY (genreId) REFERENCES genre (genreId),
FOREIGN KEY (songId) REFERENCES songs (songId)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8
DEFAULT COLLATE utf8_general_ci;
Run Code Online (Sandbox Code Playgroud)
当我在下面运行时,两个quires一切正常.
mysql> SELECT count(*) FROM songs;
+----------+
| count(*) |
+----------+
| 48959281 |
+----------+
1 row in set (9.10 sec)
mysql> SHOW PROFILE;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| starting | 0.000008 |
| Waiting for query cache lock | 0.000002 |
| checking query cache for query | 0.000019 |
| checking permissions | 0.000003 |
| Opening tables | 0.000011 |
| System lock | 0.000004 |
| Waiting for query cache lock | 0.000017 |
| init | 0.000006 |
| optimizing | 0.000003 |
| statistics | 0.000004 |
| preparing | 0.000004 |
| executing | 0.000003 |
| Sending data | 9.100444 |
| end | 0.000012 |
| query end | 0.000005 |
| closing tables | 0.000008 |
| freeing items | 0.000007 |
| Waiting for query cache lock | 0.000002 |
| freeing items | 0.000012 |
| Waiting for query cache lock | 0.000002 |
| freeing items | 0.000001 |
| storing result in query cache | 0.000002 |
| logging slow query | 0.000001 |
| cleaning up | 0.000003 |
+--------------------------------+----------+
24 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
mysql> SELECT count(*) FROM popular_songs;
+----------+
| count(*) |
+----------+
| 5721117 |
+----------+
1 row in set (1.34 sec)
mysql> SHOW PROFILE;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| starting | 0.000012 |
| Waiting for query cache lock | 0.000004 |
| checking query cache for query | 0.000037 |
| checking permissions | 0.000006 |
| Opening tables | 0.000017 |
| System lock | 0.000007 |
| Waiting for query cache lock | 0.000031 |
| init | 0.000010 |
| optimizing | 0.000017 |
| statistics | 0.000004 |
| preparing | 0.000004 |
| executing | 0.000003 |
| Sending data | 1.343991 |
| end | 0.000010 |
| query end | 0.000005 |
| closing tables | 0.000007 |
| freeing items | 0.000007 |
| Waiting for query cache lock | 0.000002 |
| freeing items | 0.000011 |
| Waiting for query cache lock | 0.000001 |
| freeing items | 0.000001 |
| storing result in query cache | 0.000002 |
| logging slow query | 0.000001 |
| cleaning up | 0.000003 |
+--------------------------------+----------+
24 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
当我在运行以下查询时,MySQL没有响应.我不明白是什么原因.
SELECT COUNT(*)
FROM songs
INNER JOIN popular_songs ON popular_songs.songId = songs.songId
Run Code Online (Sandbox Code Playgroud)
SELECT COUNT(*)
FROM songs
INNER JOIN popular_songs ON popular_songs.songId = songs.songId
WHERE songs.songDuration > 0
Run Code Online (Sandbox Code Playgroud)
更新:
MySQL回复了以上两个查询.但它需要250-300秒Sending data
.如何优化这一点.
EXPLAIN EXTENDED报告:
mysql> EXPLAIN EXTENDED
-> SELECT COUNT(*)
-> FROM songs
-> INNER JOIN popular_songs ON popular_songs.songId = songs.songId;
+----+-------------+---------------+--------+---------------+----------+---------+-----------------------------+---------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------+--------+---------------+----------+---------+-----------------------------+---------+----------+-------------+
| 1 | SIMPLE | popular_songs | index | songId | songRank | 4 | NULL | 6449163 | 100.00 | Using index |
| 1 | SIMPLE | songs | eq_ref | PRIMARY | PRIMARY | 8 | itunes.popular_songs.songId | 1 | 100.00 | Using index |
+----+-------------+---------------+--------+---------------+----------+---------+-----------------------------+---------+----------+-------------+
2 rows in set, 1 warning (0.01 sec)
mysql> EXPLAIN EXTENDED
-> SELECT COUNT(*)
-> FROM songs
-> INNER JOIN popular_songs ON popular_songs.songId = songs.songId
-> WHERE songs.songDuration > 0;
+----+-------------+---------------+--------+----------------------+----------+---------+-----------------------------+---------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------+--------+----------------------+----------+---------+-----------------------------+---------+----------+-------------+
| 1 | SIMPLE | popular_songs | index | songId | songRank | 4 | NULL | 6449163 | 100.00 | Using index |
| 1 | SIMPLE | songs | eq_ref | PRIMARY,songDuration | PRIMARY | 8 | itunes.popular_songs.songId | 1 | 100.00 | Using where |
+----+-------------+---------------+--------+----------------------+----------+---------+-----------------------------+---------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
使用INDEX songId
连接两个表时:
mysql> SELECT COUNT(*) FROM songs INNER JOIN popular_songs USE INDEX FOR JOIN (songId) ON popular_songs.songId = songs.songId;
+----------+
| COUNT(*) |
+----------+
| 5721117 |
+----------+
1 row in set (25.35 sec)
mysql> SHOW PROFILE;
+--------------------------------+-----------+
| Status | Duration |
+--------------------------------+-----------+
| starting | 0.000011 |
| Waiting for query cache lock | 0.000004 |
| checking query cache for query | 0.000045 |
| checking permissions | 0.000004 |
| checking permissions | 0.000004 |
| Opening tables | 0.000023 |
| System lock | 0.000007 |
| Waiting for query cache lock | 0.000030 |
| init | 0.000021 |
| optimizing | 0.000011 |
| statistics | 0.000020 |
| preparing | 0.000012 |
| executing | 0.000005 |
| Sending data | 25.350160 |
| end | 0.000019 |
| query end | 0.000005 |
| closing tables | 0.000024 |
| freeing items | 0.000022 |
| Waiting for query cache lock | 0.000002 |
| freeing items | 0.000016 |
| Waiting for query cache lock | 0.000001 |
| freeing items | 0.000001 |
| storing result in query cache | 0.000002 |
| logging slow query | 0.000001 |
| logging slow query | 0.000005 |
| cleaning up | 0.000003 |
+--------------------------------+-----------+
26 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
这很不错.但是,它还需要25秒Sending data
.
解释以上查询的扩展:
mysql> EXPLAIN EXTENDED SELECT COUNT(*) FROM songs INNER JOIN popular_songs USE INDEX FOR JOIN (songId) ON popular_songs.songId = songs.songId;
+----+-------------+---------------+--------+---------------+---------+---------+-----------------------------+---------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------+--------+---------------+---------+---------+-----------------------------+---------+----------+-------------+
| 1 | SIMPLE | popular_songs | index | songId | songId | 8 | NULL | 2684407 | 100.00 | Using index |
| 1 | SIMPLE | songs | eq_ref | PRIMARY | PRIMARY | 8 | itunes.popular_songs.songId | 1 | 100.00 | Using index |
+----+-------------+---------------+--------+---------------+---------+---------+-----------------------------+---------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
我猜测索引songDuration
会让优化器混乱.您可以尝试像这样填写查询:
SELECT COUNT(*)
FROM songs s
WHERE EXISTS (SELECT 1
FROM popular_songs ps
WHERE ps.songId = s.songId
) AND
s.songDuration > 0;
Run Code Online (Sandbox Code Playgroud)
指数songDuration
也会更好地包括在内songId
: songs(songDuration, songId)
.
归档时间: |
|
查看次数: |
1047 次 |
最近记录: |