1. 程式人生 > >sql優化經典例子-轉載

sql優化經典例子-轉載

場景

我用的資料庫是mysql5.6,下面簡單的介紹下場景

課程表

create table Course(

c_id int PRIMARY KEY,

name varchar(10)

)

資料100條

學生表:

create table Student(

id int PRIMARY KEY,

name varchar(10)

)

資料70000條

學生成績表SC

CREATE table SC(

    sc_id int PRIMARY KEY,

    s_id int,

    c_id int,

    score int

)

資料70w條

查詢目的:

查詢語文考100分的考生

查詢語句:

select s.* from
Student s where s.s_id in (select s_id from SC sc where sc.c_id = 0 and sc.score = 100 )

執行時間:30248.271s

暈,為什麼這麼慢,先來檢視下查詢計劃:

EXPLAIN 

select s.* from Student s where s.s_id in (select s_id from SC sc where sc.c_id = 0 and sc.score = 100 )

image

發現沒有用到索引,type全是ALL,那麼首先想到的就是建立一個索引,建立索引的欄位當然是在where條件的欄位。

先給sc表的c_id和score建個索引

CREATE index sc_c_id_index on SC(c_id);
CREATE index sc_score_index on SC(score);

再次執行上述查詢語句,時間為: 1.054s

快了3w多倍,大大縮短了查詢時間,看來索引能極大程度的提高查詢效率,看來建索引很有必要,很多時候都忘記建

索引了,資料量小的的時候壓根沒感覺,這優化感覺挺爽。

但是1s的時間還是太長了,還能進行優化嗎,仔細看執行計劃:

image

檢視優化後的sql:

SELECT
    `YSB`.`s`.`s_id` AS `s_id`,
    `YSB`.`s`.`name` AS `name`
FROM
    `YSB`
.`Student` `s` WHERE < in_optimizer > ( `YSB`.`s`.`s_id` ,< EXISTS > ( SELECT 1 FROM `YSB`.`SC` `sc` WHERE ( (`YSB`.`sc`.`c_id` = 0) AND (`YSB`.`sc`.`score` = 100) AND ( < CACHE > (`YSB`.`s`.`s_id`) = `YSB`.`sc`.`s_id` ) ) ) )

補充:這裡有網友問怎麼檢視優化後的語句

方法如下:

在命令視窗執行 image

image

有type=all

按照我之前的想法,該sql的執行的順序應該是先執行子查詢

select s_id from SC sc where sc.c_id = 0 and sc.score = 100

耗時:0.001s

得到如下結果:

image

然後再執行

select s.* from Student s where s.s_id in(7,29,5000)

耗時:0.001s

這樣就是相當快了啊,Mysql竟然不是先執行裡層的查詢,而是將sql優化成了exists子句,並出現了EPENDENT SUBQUERY,

mysql是先執行外層查詢,再執行裡層的查詢,這樣就要迴圈70007*11=770077次。

那麼改用連線查詢呢?

SELECT s.* from 

Student s

INNER JOIN SC sc

on sc.s_id = s.s_id

where sc.c_id=0 and sc.score=100

這裡為了重新分析連線查詢的情況,先暫時刪除索引sc_c_id_index,sc_score_index

執行時間是:0.057s

效率有所提高,看看執行計劃:

image

這裡有連表的情況出現,我猜想是不是要給sc表的s_id建立個索引

CREATE index sc_s_id_index on SC(s_id);

show index from SC

image

在執行連線查詢

時間: 1.076s,竟然時間還變長了,什麼原因?檢視執行計劃:

image

優化後的查詢語句為:

SELECT
    `YSB`.`s`.`s_id` AS `s_id`,
    `YSB`.`s`.`name` AS `name`
FROM
    `YSB`.`Student` `s`
JOIN `YSB`.`SC` `sc`
WHERE
    (
        (
            `YSB`.`sc`.`s_id` = `YSB`.`s`.`s_id`
        )
        AND (`YSB`.`sc`.`score` = 100)
        AND (`YSB`.`sc`.`c_id` = 0)
    )

貌似是先做的連線查詢,再執行的where過濾

回到前面的執行計劃:

image

這裡是先做的where過濾,再做連表,執行計劃還不是固定的,那麼我們先看下標準的sql執行順序:

image

正常情況下是先join再where過濾,但是我們這裡的情況,如果先join,將會有70w條資料傳送join做操,因此先執行where

過濾是明智方案,現在為了排除mysql的查詢優化,我自己寫一條優化後的sql

SELECT
    s.*
FROM
    (
        SELECT
            *
        FROM
            SC sc
        WHERE
            sc.c_id = 0
        AND sc.score = 100
    ) t
INNER JOIN Student s ON t.s_id = s.s_id

即先執行sc表的過濾,再進行表連線,執行時間為:0.054s

和之前沒有建s_id索引的時間差不多

檢視執行計劃:

image

先提取sc再連表,這樣效率就高多了,現在的問題是提取sc的時候出現了掃描表,那麼現在可以明確需要建立相關索引

CREATE index sc_c_id_index on SC(c_id);
CREATE index sc_score_index on SC(score);

再執行查詢:

SELECT
    s.*
FROM
    (
        SELECT
            *
        FROM
            SC sc
        WHERE
            sc.c_id = 0
        AND sc.score = 100
    ) t
INNER JOIN Student s ON t.s_id = s.s_id

執行時間為:0.001s,這個時間相當靠譜,快了50倍

執行計劃:

image

我們會看到,先提取sc,再連表,都用到了索引。

那麼再來執行下sql

SELECT s.* from 

Student s

INNER JOIN SC sc

on sc.s_id = s.s_id

where sc.c_id=0 and sc.score=100

執行時間0.001s

執行計劃:

image

這裡是mysql進行了查詢語句優化,先執行了where過濾,再執行連線操作,且都用到了索引。

總結:

1.mysql巢狀子查詢效率確實比較低

2.可以將其優化成連線查詢

3.建立合適的索引

4.學會分析sql執行計劃,mysql會對sql進行優化,所以分析執行計劃很重要

由於時間問題,這篇文章先寫到這裡,後續再分享其他的sql優化經歷。

相關推薦

sql優化經典例子-轉載

場景我用的資料庫是mysql5.6,下面簡單的介紹下場景課程表create table Course( c_id int PRIMARY KEY, name varchar(10) )資料100條學生表:create table Student( id int PRI

sql優化經典例子

場景 我用的資料庫是mysql5.6,下面簡單的介紹下場景 課程表 create table Course( c_id int PRIMARY KEY, name varchar(10) ) 資料100條 學生表: create table Stude

SQL行轉列經典例子(轉載)

htm har server2 str union sdn ltrim sql ue4 行轉列問題總結 1、行轉列 ---1、最簡單的行轉列 /* 問題:假設有張學生成績表(tb)如下: 姓名 課程 分數 張三 語文 74 張三 數學 83 張三 物理 93 李

SQL優化經典案例合集

       駐場銀行,很多案例當時處理了寫完報告,卻無法拷貝出來,你懂得!只能等合適的"機會",讓人"幫忙"給假釋出來,所以我的部落格不更新則以一更新就是一大坨……在案例關押期間,曾因為伺服器變更、加盤、誤操作等問題,很多案例無故失蹤…實則痛心疾首…好在有些案例終於刑滿釋放

索引原理和SQL優化轉載待整理)

索引的本質 MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取資料的資料結構。提取句子主幹,就可以得到索引的本質:索引是資料結構。 我們知道,資料庫查詢是資料庫的最主要功能之一。我們都希望查詢資料的速度能儘可能的快,因此資料庫系統的設計者會從查詢演算法的角度進行優化。最

(ainusers轉載優秀文章)SQL優化之my.cnf

[client] default-character-set=utf8mb4 #mysqlde utf8字符集預設為3位的,不支援emoji表情及部分不常見的漢字,故推薦使用utf8mb4   [mysql] default-character-set=utf8mb4   [my

SQL優化理論基礎:MySQL架構總覽、查詢執行流程、SQL解析順序(轉載

前言:   一直是想知道一條SQL語句是怎麼被執行的,它執行的順序是怎樣的,然後檢視總結各方資料,就有了下面這一篇博文了。   本文將從MySQL總體架構--->

經典SQL語句大全-【轉載自】部落格園,作者部落格:YuBinfeng's Technology Blog

因最近學習MySQL,閒來無事逛帖子時,發現這篇較為經典的部落格,特轉載以防備用學習,同時希望也可以幫到他人,廢話不多說,進入正文  一、基礎 1、說明:建立資料庫 CREATE DATABASE database-name 2、說明:刪除資料庫 drop data

資料庫SQL查詢的經典例子

正如老師在作業系統裡引用的話,我不妨拿來套用一下---複習資料庫有種不知道自己姓啥的感覺,尤其在面對戰老師這華麗麗的四連招時,真是快招架不住,不過老師的必殺卻能幫助我們更好的理解和區分元組演算和關係代數。於是記下來準備接招......已知:學生關係:Student(S#,

SQL優化基礎:使用索引(一個小例子

       一年多沒寫,偶爾會有衝動寫幾句,每次都欲寫又止,有時候寫出來就是個記錄,沒有其他想法,能對別人有用也算額外的功勞 按照本文操作和體會,會對sql優化有個基本最簡單的瞭解,其他深入還需要更多資料和實踐的學習: 1. 建表: create table site_user ( id

避免全表掃描的sql優化

設計 結束 edate bstr 需要 表達 大量數據 第一個 關鍵字 摘抄自:http://www.cnblogs.com/jameslif/p/6406167.html 對查詢進行優化,應盡量避免全表掃描,首先應考慮在where 及order by 涉及的列上建立索引

SQL優化SQL TUNING)之10分鐘完畢億級數據量性能優化SQL調優)

font 一個 進一步 結束 語句 pop 技術分享 處理 fill 前幾天。一個用戶研發QQ找我,例如以下: 自由的海豚。 16:12:01 島主,我的一條SQL查不出來結果,能幫我看看不? 蘭花島主 16:12:10 多久不出結果? 自由的海豚 16:12:17

mysql sql優化

ner jdbc連接 htm database 提升 第一個 記錄 blog bat 記錄一些經驗,主要是結論。建檢索等就不寫了,地球人都知道。 1. 對比2個join select * from (select * from A where age > 10

SQL優化-子查詢&case&limit

子查詢優化load 導數據.notesdxtdb 數據庫 total_time 475.60秒。 監控服務:倉頡select t_.*, a.name acquirer_name,m.merchant_name, am.merchant_name acq_merchant_name,

MySQL專題3 SQL 優化

prim ofa 建立 運行 關註 intersect order by 獲得 專題 這兩天去京東面試,面試官問了我一個問題,如何優化SQL 我上網查了一下資料,找到了不少方法,做一下記錄 (一)、 首先使用慢查詢分析 通過Mysql 的Slow Query log

遞歸的幾個經典例子

void har logs 階乘 tin scan mov rom n) 註意:構造方法不可遞歸,否則是無限創建對象; 遞歸的幾個經典例子: 1.HannoiTower 1 import java.util.Scanner; 2 public class Han

sql優化(oracle)- 第二部分 常用sql用法和註意事項

個數 its 用法 記錄 減少 合並 .com 語句 一個 第二部分 常用sql用法和註意事項 1. exists 和 in 2. union 和 union all

sql優化(oracle)- 第三部分  sql優化總結

mit 設計 tinc 重復 tin spa 替代 嵌套 多個 第三部分 sql優化總結 1. 優化一般原則 2. 具體註意事項 1. SQL優化一般性原則  1)目標:減少服務器資源消耗(主要是磁盤IO)  2)設計:    1. 盡量依

SQL優化

存儲 col substring truncate 調整 查詢優化 復合 drop 過程 1.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。2.應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致

常用SQL優化(一),提升運算效率

大數據 必須 -name 過大 一半 一次 存儲過程 是否 ins 網上關於SQL優化的教程很多,但是比較雜亂。近日有空整理了一下,寫出來跟大家分享一下,其中有錯誤和不足的地方,還請大家糾正補充。1.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 orde