Mysql - 性能優化之子查詢

来源:http://www.cnblogs.com/elvinle/archive/2017/01/03/6237147.html
-Advertisement-
Play Games

記得在做項目的時候, 聽到過一句話, 儘量不要使用子查詢, 那麼這一篇就來看一下, 這句話是否是正確的. 那在這之前, 需要介紹一些概念性東西和mysql對語句的大致處理. 當Mysql Server的連接線程接收到Client發送過來的SQL請求後, 會經過一系列的分解Parse, 進行相應的分析 ...


記得在做項目的時候, 聽到過一句話, 儘量不要使用子查詢, 那麼這一篇就來看一下, 這句話是否是正確的.

那在這之前, 需要介紹一些概念性東西和mysql對語句的大致處理.

當Mysql Server的連接線程接收到Client發送過來的SQL請求後, 會經過一系列的分解Parse, 進行相應的分析, 然後Mysql會通過查詢優化器模塊, 根據該Sql所涉及到的數據表的相關統計信息進行計算分析. 然後在得出一個Mysql自認為最合理最優化的數據訪問方式, 也就是我們常說的"執行計劃", 然後根據所得到的執行計劃通過調用存儲引擎介面來獲取相應數據. 再對存儲引擎返回的數據進行相關的處理, 並一Client端所要求的格式作為結果集, 返回給Client.

註 : 這裡所說的統計數據, 是我們通過 Analyze table命令通知Mysql對錶的相關數據作分析之後, 所獲取到的一些數據統計量. 這些數據對Mysql優化器而言是非常重要的, 優化器所生成的執行計劃的好壞, 主要是由這些統計數據所決定的.

1. 建表

create table User(
  Id int not null PRIMARY key auto_increment ,
  NickName varchar(50) comment '用戶昵稱',
  Sex int comment '性別',
  Sign varchar(50) comment '用戶簽名',
  Birthday datetime comment '用戶生日',
  CreateTime datetime comment '創建時間'
) default charset=utf8 comment '用戶表';

create table UserGroup(
  Id int not null PRIMARY key auto_increment ,
  UserId int not null comment 'user Id',
  GroupId int not null comment '用戶組Id',
  CreateTime datetime comment '創建時間',
  -- key index_groupid(GroupId) using btree,
  key index_userid(groupid, UserId) using btree
) default charset=utf8 comment '用戶組表';

2. 準備數據

var conStr = ConfigurationManager.ConnectionStrings["ConStr"].ToString();
using (IDbConnection conn = new MySqlConnection(conStr))
{
    Stopwatch watch = new Stopwatch();
    var sql = string.Empty;
    var names = new string[] { "", "", "", "", "", "", "", "", "" };
    Random ran = new Random();  
    var insertSql = @" insert into User(NickName,Sex,Sign, Birthday, CreateTime) values(@NickName,@Sex,@Sign, @Birthday, @CreateTime); 
    INSERT INTO usergroup  (UserId,  GroupId,  CreateTime )  VALUES (LAST_INSERT_ID() ,   @GroupId,  @CreateTime);";
    watch.Start();
    if (conn.State == ConnectionState.Closed)
    {
        conn.Open();
    }

    var tran = conn.BeginTransaction();
    for (int i = 0; i < 100000; i++)
    {
        var param = new { NickName = names[ran.Next(9)] + names[ran.Next(9)] + i, Sign = names[ran.Next(9)] + names[ran.Next(9)], CreateTime = DateTime.Now, Birthday = DateTime.Now.AddYears(ran.Next(10, 30)), Sex = i % 2, GroupId = ran.Next(1, 100) };
        conn.Execute(insertSql, param, tran);
    }
    tran.Commit();

    conn.Dispose();
    watch.Stop();
    Console.WriteLine(watch.ElapsedMilliseconds);
}

這裡我插入了5000條數據, group分了99個組, 隨機的. 

 

3. 查詢sql

 explain
select user.id, user.nickname from usergroup 
left join user  on usergroup.UserId = user.Id
where  usergroup.groupid = 1 
order by usergroup.UserId desc
limit 100, 20;

 explain
select user.id, user.nickname
from (select id, userid from usergroup where groupid = 1 order by userid limit 100, 20) t
left join  user on t.UserId = user.id ;

 explain
select user.id, user.nickname
from (select id, userid from usergroup where groupid = 1 order by userid ) t
left join  user on t.UserId = user.id 
limit 100, 20;

 

第二句和第三句都使用到了子查詢, 不同之處再與, 第二句是先得到20條數據, 然後以此來與user表關聯的

 

4. 分析

100000條數據情況下 : 

先看第一句

 

再看第二句

 

第三句

從上面三幅圖看, 好像能看出點什麼了.

首先看他們的 rows, 第二句最多, 加起來有1000多了, 另兩句加起來都是996. 但是我想說的是, 這裡並不是看rows的和是多少. 正確的方式是, 從id大的語句開始看, id相同的語句, 從上到下依次執行.

那先看第二句的id=2的語句和第一句的id=1的語句, 一模一樣的. 他們都是從usergroup表中篩選數據, 並且能得到相同的結果集A.

看來他們都是基於相同的結果集去進行操作, 接下來就有區別了.

先看第一句, 再結果集A的基礎上, 去左連接表user, 並篩選出最後的數據, 返回給客戶端.

那第二句呢, 是在A的基礎上, 再次篩選數據, 得到需要的數據, 然後拿這些數據, 去與user表左連接, 得到最終結果.

從上面來看, 執行計劃中, 第二種執行計劃, 更加高效. 

 如果能夠通過子查詢, 大幅度縮小查詢範圍, 可以考慮使用子查詢語句. 

 

 參考:

  Mysql性能優化explain


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、AJAX示例1.1、優點1.2、缺點1.3、jQuery AJAX示例二、延遲對象(Deferred)2.1、回調函數2.2、deferred.done三、跨域3.1、什麼是跨域3.2、JSONP跨域3.3、jQuery使用JSONP跨域3.4、跨域資源共用(CORS)3.5、小結四、彈出層五、... ...
  • 一、前端MVC概要 1.1、庫與框架的區別 框架是一個軟體的半成品,在全局範圍內給了大的約束。庫是工具,在單點上給我們提供功能。框架是依賴庫的。AngularJS是框架而jQuery則是庫。 1.2、AMD與CMD 在傳統的非模塊化JavaScript開發中有許多問題:命名衝突、文件依賴、跨環境共用 ...
  • 查看npm的所有版本 運行命令: 命令運行後,會輸出到目前為止npm的所有版本。 將npm升級到某個版本。 升級前本機版本號是2.14.12,可通過npm -v查看。 命令運行,升級到3.1.0版: 升級完成後,查看一下本機npm的版本,就是升級後的版本。 參考: Updating npm ...
  • 01.01_電腦基礎知識(電腦概述)(瞭解) A:什麼是電腦?電腦在生活中的應用舉例 電腦(Computer)全稱:電子電腦,俗稱電腦。是一種能夠按照程式運行,自動、高速處理海量數據的現代化智能電子設備。由硬體和軟體所組成,沒有安裝任何軟體的電腦稱為裸機。常見的形式有台式電腦、筆記本 ...
  • 一、下載並安裝class-dump 下載class-dump-3.5.dmg 點擊下載 下載完成以後雙擊.dmg的文件,將裡面的class-dump拷貝到/usr/local/bin 設置許可權chmod 777 /usr/local/bin/class-dump 在控制台輸入class-dump,顯 ...
  • JDK安裝與配置 一、下載 JDK是ORACLE提供免費下載使用的,官網地址:https://www.oracle.com/index.html 一般選擇Java SE版本即可,企業版的選擇Java EE 下載的JDK版本(目前最新的是JDK8u112) JDK的開發包以及相關的文檔下載 勾選同意, ...
  • 轉載請註明出處:http://www.cnblogs.com/Joanna-Yan/p/6241354.html 首先看一張國內Top500 Android應用中它們用到的第三方推送以及所占數量: 現在總結下Android平臺下幾種推送方案的基本情況以及優缺點: 一、使用GCM(Google Clo ...
  • SqlServer的性能問題大部分是因為缺少索引或索引不當導致的,因此熟悉掌握索引相關知識是精通SqlServer的第一步。我們可以從索引的數據結構瞭解索引的本質;掌握聚集索引和非聚集索引的區別有助於我們在不同場景下走出誤區、建立合適索引;在一些場景下你也有可能需要用到索引視圖 索引的數據結構 在S ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...