我很難處理查詢優化,我相信目前使用的查詢優化可以改進很多。
我有 4 張桌子;
Artist (14,930 rows)
| 藝術家 ID | 藝術家名 | 藝術家蛞蝓 | 藝術家國家 |
|---|---|---|---|
| 1 | 艾麗 | 艾麗 | 5 |
Country (85 rows)
| country_id | 國家的名字 | country_slug |
|---|---|---|
| 1 | 美國 | 美國 |
Song (61,119 rows)
| 歌曲編號 | 歌名 | song_artist_id | 歌曲播放 |
|---|---|---|---|
| 1 | 小貓貓 | 1 | 38291 |
| 2 | 驢 | 1 | 8291 |
Lyrics (61,119 rows)
| 歌詞ID | 歌詞_歌曲_id | 歌詞正文 |
|---|---|---|
| 1 | 1 | Kitty Kat 歌詞 |
| 2 | 2 | 驢歌詞 |
我正在使用此查詢加入表格,獲取單個藝術家的資料加上、國家、歌曲總數、藝術家在所有歌曲上播放的總和以及歌詞總數。
SELECT /* MAX_EXECUTION_TIME(2000) */
artist.*,
country.*,
COUNT(song.song_id) AS TotalSongs,
COUNT(lyrics.lyrics_id) AS TotalLyrics,
SUM(song.song_plays) AS TotalPlays
FROM artist
LEFT JOIN country ON artist.artist_country_id = country.country_id
LEFT JOIN song ON artist.artist_id = song.song_artist_id
LEFT JOIN lyrics ON song.song_id = lyrics.lyrics_song_id
WHERE artist_status = 'enabled' AND artist.artist_slug = '$slug'
GROUP BY artist.artist_id LIMIT 0, 1
如何改進它以更快地執行并使用更少的資源?
提前致謝。
uj5u.com熱心網友回復:
我會簡單地在 select 子句中使用子查詢進行聚合:
SELECT artist.*, country.*, (
SELECT COUNT(*)
FROM song
WHERE song.song_artist_id = artist.artist_id
) AS total_songs, (
SELECT SUM(song_plays)
FROM song
WHERE song.song_artist_id = artist.artist_id
) AS total_plays, (
SELECT COUNT(*)
FROM song
JOIN lyrics ON song.song_id = lyrics.lyrics_song_id
WHERE song.song_artist_id = artist.artist_id
) AS total_lyrics
FROM artist
LEFT JOIN country ON artist.artist_country_id = country.country_id
WHERE artist_status = 'enabled'
AND artist.artist_slug = :slug
在 MySQL 8 或更高版本中,您可以使用橫向連接:
SELECT artist.*, country.*, lj.*
FROM (artist LEFT JOIN country ON artist.artist_country_id = country.country_id), LATERAL (
SELECT COUNT(song.song_id) total_songs, SUM(song_plays) total_plays, COUNT(lyrics.lyrics_id) total_lyrics
FROM song
LEFT JOIN lyrics ON song.song_id = lyrics.lyrics_song_id
WHERE song.song_artist_id = artist.artist_id
) AS lj
WHERE artist_status = 'enabled'
AND artist.artist_slug = :slug
uj5u.com熱心網友回復:
在表上創建所有索引,其列為:
CREATE INDEX index_name1 ON artist (artist_country_id );
CREATE INDEX index_name2 ON country (country_id);
CREATE INDEX index_name3 ON artist (artist_id );
CREATE INDEX index_name4 ON song (song_artist_id);
CREATE INDEX index_name5 ON artist (artist_status );
并創建一個這樣的視圖:
CREATE VIEW customerPayments
AS
SELECT /* MAX_EXECUTION_TIME(2000) */
artist.*,
country.*,
COUNT(song.song_id) AS TotalSongs,
COUNT(lyrics.lyrics_id) AS TotalLyrics,
SUM(song.song_plays) AS TotalPlays
FROM artist
LEFT JOIN country ON artist.artist_country_id = country.country_id
LEFT JOIN song ON artist.artist_id = song.song_artist_id
LEFT JOIN lyrics ON song.song_id = lyrics.lyrics_song_id
WHERE artist_status = 'enabled' AND artist.artist_slug = '$slug'
GROUP BY artist.artist_id LIMIT 0, 1;
視圖是存盤在資料庫目錄中的命名查詢
View 并不物理存盤資料。當您針對視圖發出 SELECT 陳述句時,MySQL 執行視圖定義中指定的基礎查詢并回傳結果集。因此,有時將視圖稱為虛擬表。
物化視圖 (MV) 是查詢的預計算(物化)結果。與簡單的 VIEW 不同,物化視圖的結果存盤在某處,通常在 table 中。當需要立即回應并且物化視圖所基于的查詢需要很長時間才能產生結果時,使用物化視圖。物化視圖必須不時重繪 。這取決于物化視圖的重繪 頻率及其內容的實際程度。基本上,物化視圖可以立即或延遲重繪 ,它可以完全重繪 或到某個時間點。MySQL 本身不提供物化視圖。但是自己構建物化視圖很容易。
由于物化視圖基于快取獲取資料,因此它們比視圖更快。Mysql中沒有物化視圖的概念。但是你可以通過https://fromdual.com/mysql-materialized-views 實作自己的物化視圖
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/478051.html
