Mysql 優化與測試

来源:http://www.cnblogs.com/zhenghongxin/archive/2017/09/11/7504130.html
-Advertisement-
Play Games

以下的測試數據根據環境的不同所耗費的時間有所不同,例如我在騰訊雲上的測試,以及在本機的測試速度相差三倍。但當環境因素一樣的時候,優化sql能夠帶來顯著的提升。 測試表數據:3百萬條數據,12個欄位,存儲引擎:myisam 1 確定搜索一條記錄的時候,加上limit 1 ,以此讓游標查到第一條結果時停 ...


以下的測試數據根據環境的不同所耗費的時間有所不同,例如我在騰訊雲上的測試,以及在本機的測試速度相差三倍。但當環境因素一樣的時候,優化sql能夠帶來顯著的提升。

測試表數據:3百萬條數據,12個欄位,存儲引擎:myisam

1 確定搜索一條記錄的時候,加上limit 1 ,以此讓游標查到第一條結果時停止,不需要遍歷下麵的結果

image

使用這樣子數據遞增的varchar欄位,在最優情況下,結果在第一條:

SQL : select * from tbl_game_user_test where channel= 'jieduan1';

TIME : 1.292 s

而當我們加上了limit 1 :

SQL : select * from tbl_game_user_test where channel= 'jieduan1' limit 1;

TIME : 0.0001 s 

對比上面,提高了很多。而在最壞情況下,結果在最後一條,那麼兩者使用時間是一致的。

而當我們explain的時候,兩者是一致的:

+----+-------------+--------------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table              | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+--------------------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | tbl_game_user_test | ALL  | NULL          | NULL | NULL    | NULL | 3006343 | Using where |
+----+-------------+--------------------+------+---------------+------+---------+------+---------+-------------+

2 like查詢以%開頭索引會失效,沒有命中索引,查詢效率差別是很大的。而%在結尾,可以命中索引

未優化的sql:

SQL:select * from tbl_game_user_test where deviceID LIKE '%deviceID1111111'

TIME : 2.342 s

而當我們將%放到末尾:

SQL : select * from tbl_game_user_test where deviceID LIKE 'deviceID1111111%';

TIME : 0.001 s

花費的時間相差挺大

3 對於分頁的優化,可以採用覆蓋索引的原理來優化。

在數據量不大的時候,limit 分頁效率差別不大,當數據量大的時候,數據越大,效率差距越大,因此我們可以採用覆蓋索引的原理,來優化sql。

未優化前SQL:

SELECT * FROM tbl_game_user_test ORDER BY id LIMIT 1000000,10

Times : 4.55 s

而優化的SQL:

select * from tbl_game_user_test JOIN (SELECT id FROM tbl_game_user_test ORDER BY id LIMIT 100000,10)a USING(id)

Times : 0.014s

我們把第二種檢索方法叫做延遲關聯,因為延遲了對列的訪問。在查詢的第一階段MySQL可以使用覆蓋索引,在FROM字句的查詢中找到匹配的id,然後根據這些id值在外層查詢匹配獲取需要的列值

上述的語句,我們也可以這麼寫:

select * from tbl_game_user_test where id >=(SELECT id FROM tbl_game_user_test ORDER BY id LIMIT 100000,1) ORDER BY id limit 10

4 永遠為每張表設置一個ID

  我們應該為資料庫里的每張表都設置一個ID做為其主鍵,而且最好的是一個INT型的(推薦使用UNSIGNED),並設置上自動增加的 AUTO_INCREMENT標誌。
就算是你 users 表有一個主鍵叫 “email”的欄位,你也別讓它成為主鍵。使用 VARCHAR 類型來當主鍵會使用得性能下降。另外,在你的程式中,你應該使用表的ID來構造你的數據結構。
而且,在MySQL數據引擎下,還有一些操作需要使用主鍵,在這些情況下,主鍵的性能和設置變得非常重要,比如,集群,分區……

5 合適的存儲引擎

  InnoDB和MyISAM是許多人在使用MySQL時最常用的兩個表類型,這兩個表類型各有優劣,視具體應用而定。基本的差別為:MyISAM類型不支持事務處理等高級處理,而InnoDB類型支持。MyISAM類型的表強調的是性能,其執行數度比InnoDB類型更快,但是不提供事務支持,而InnoDB提供事務支持以及外部鍵等高級資料庫功能。

同樣的情況下,執行相同的查詢,myisam 比innodb 快接近4倍;

存儲引擎 : myisam

SQL :select * from tbl_game_user_test where channel = 'jieduan65';

time : 1.2 s

而 : innodb 是 4.6s  【平均】

6 Mysql SQL Mode 可以禁止截斷保存操作

當我們對一個varchar(3)的欄位進行更新操作:

update tbl_game_user_test set platform  = 'jieduanTest' where id = 1;

我們發現插入的字元被自動截斷了,

存入的是:

jie

出現這種情況往往會發生一些意料之外的事情,等到發生了,再來找問題,再擴大欄位長度就比較晚。我們可以在長度超過限制就報錯,通過報錯來提前報警。

可以通過:

set session sql_mode='STRICT_TRANS_TABLES'

就會提示:

[Err] 1406 - Data too long for column 'platform' at row 1

7 負向條件查詢不能使用索引

select * from order where status!=0 and stauts!=1

not in/not exists都不是好習慣

可以優化為in查詢:

select * from order where status in(2,3)

8 優化order by 語句

在某些情況中,MySQL 可以使用一個索引來滿足ORDER BY 子句,而不需要額外的排序。where 條件和order by 使用相同的索引,並且order by 的順序和索引順序相同,並且order by 的欄位都是升序或者都是降序。
例如:下列sql 可以使用索引。

SELECT * FROM t1 ORDER BY key_part1,key_part2,... ;
SELECT
* FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC, key_part2 DESC;
SELECT
* FROM t1 ORDER BY key_part1 DESC, key_part2 DESC;

但是以下情況不使用索引:

SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
--order by 的欄位混合ASC 和DESC
SELECT
* FROM t1 WHERE key2=constant ORDER BY key1; --用於查詢行的關鍵字與ORDER BY 中所使用的不相同
SELECT
* FROM t1 ORDER BY key1, key2; --對不同的關鍵字使用ORDER BY:

 其他優化小技巧:

1 字元欄位只建首碼索引

2 導入大數據量時,先刪除索引,導入數據,再創建索引

3 在設計表的時候,可以按照定長欄位與變長欄位相分離,分開兩個表存放。例如論壇標題是我們經常獲取的,而論壇個人創建時間等,幾乎是不會去看,這種我們可以放於幾乎不查的表中。同時,我們也可以把較長內容的欄位獨立存放於一個表中。

4 冗餘欄位。很多時候我們設計表都要遵守第一,二,三範式,但有時我們為了加快查詢,而應該添加冗餘欄位。例如論壇欄目表中,一般而言,我們會有個欄目表,有文章表,而當我們獲取該欄目有多少篇文章的時候,聯表查詢顯得稍費時間,而我們可以在欄目表添加一個文章數量欄位,每次添加或者刪除都更新一下該欄位。


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

-Advertisement-
Play Games
更多相關文章
  • 1 if (!Object.keys) { 2 Object.keys = (function () { 3 var hasOwnProperty = Object.prototype.hasOwnProperty, //原型上的方法,只取自身有的屬性; 4 hasDontEnumBug = !({... ...
  • 1.註釋: html的註釋:<!--我是註釋--> CSS的註釋:/*我是註釋*/ JS的註釋://我是註釋 2.變數: 變數要先聲明再賦值,如下: var mychar; mychar="javascript"; var mynum = 6; 變數可以重覆賦值,如下: var mychar; my ...
  • 任務 1.在第27行處補充完整,實現當點擊"全選"按鈕時,將選中所有的覆選項。 提示:document.getElementsByTagName("input")獲取的是所有input標簽,包括覆選項和按鈕,所以要判斷是否是覆選項,如是選中。 2.在第33行處補充完整,實現當點擊"全不選"按鈕時,將 ...
  • JavaScript正則表達式入門 ===================== 常常用戶在一個網頁里登錄註冊帳號時,要輸入用戶名、手機號、郵箱地址、設置密碼等項目。而對於用戶輸入的用戶名是否規範,輸入的是否是郵箱地址、密碼強度如何等等都可以通過一 正則表達式 制定相應的規則來驗證校檢,來實現一個非常 ...
  • 前面的話 本文將通過多種方式實現紋理文本的效果 背景裁切 對於實現紋理文本的效果,腦海中最直接能想到的辦法可能是背景裁切background-clip 使用線性漸變來填充文本背景 下麵使用一張楓葉的背景,來製作紋理文本 當然了,放一張動態gif圖,也是沒問題的 如果想要讓填充動起來,可以通過anim ...
  • 在學習微信小程式開發過程中,一部分的難點是前端邏輯的處理,也就是對前端JS的代碼編輯;一部分的難點是前端界面的設計展示;本篇隨筆基於一個豆瓣電影介面的小程式開源項目進行重新調整,把其中遇到的相關難點和改進的地方進行討論介紹,希望給大家提供一個參考的思路,本篇隨筆是基於前人小程式的項目基礎上進行的改進... ...
  • 所謂的iOS 國際化,就是根據系統不同的語言自動切換。 首先,如圖: 所謂的iOS 國際化,就是根據系統不同的語言自動切換。 首先,如圖: 1.png 1.png 創建一個.strings文件,以“Localizable.strings”為文件名: 2.png 創建完之後,在XCode的右邊勾選自己 ...
  • 轉載請註明出處: 在Android中可以調用自帶的瀏覽器,或者指定一個瀏覽器來打開一個鏈接。只需要傳入一個uri,可以是鏈接地址。 啟動android預設瀏覽器 在Android程式中我們可以通過發送隱式Intent來啟動系統預設的瀏覽器。如果手機本身安裝了多個瀏覽器而又沒有設置預設瀏覽器的話,系統 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...