真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

MySQL優(yōu)化技巧有哪些

本篇內(nèi)容主要講解“MySQL優(yōu)化技巧有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“MySQL優(yōu)化技巧有哪些”吧!

成都創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比慶陽網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式慶陽網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋慶陽地區(qū)。費(fèi)用合理售后完善,十年實體公司更值得信賴。

SQL 優(yōu)化已經(jīng)成為衡量程序猿優(yōu)秀與否的硬性指標(biāo),甚至在各大廠招聘崗位職能上都有明碼標(biāo)注,如果是你,在這個問題上能吊打面試官還是會被吊打呢?

有朋友疑問到,SQL 優(yōu)化真的有這么重要么?如下圖所示,SQL 優(yōu)化在提升系統(tǒng)性能中是:成本最低和優(yōu)化效果最明顯的途徑。

如果你的團(tuán)隊在 SQL 優(yōu)化這方面搞得很優(yōu)秀,對你們整個大型系統(tǒng)可用性方面無疑是一個質(zhì)的跨越,真的能讓你們老板省下不止幾沓子錢。

MySQL優(yōu)化技巧有哪些

優(yōu)化成本:硬件>系統(tǒng)配置>數(shù)據(jù)庫表結(jié)構(gòu)>SQL 及索引。

優(yōu)化效果:硬件<系統(tǒng)配置<數(shù)據(jù)庫表結(jié)構(gòu)

String result = "嗯,不錯,";  if ("SQL優(yōu)化經(jīng)驗足") {      if ("熟悉事務(wù)鎖") {          if ("并發(fā)場景處理666") {              if ("會打王者榮耀") {                  result += "明天入職"               }          }      }  } else {      result += "先回去等消息吧";  }   Logger.info("面試官:" + result );

別看了,上面這是一道送命題。

好了我們言歸正傳,首先,對于MySQL層優(yōu)化我一般遵從五個原則:

  •  減少數(shù)據(jù)訪問:設(shè)置合理的字段類型,啟用壓縮,通過索引訪問等減少磁盤 IO。

  •  返回更少的數(shù)據(jù):只返回需要的字段和數(shù)據(jù)分頁處理,減少磁盤 IO 及網(wǎng)絡(luò) IO。

  •  減少交互次數(shù):批量 DML 操作,函數(shù)存儲等減少數(shù)據(jù)連接次數(shù)。

  •  減少服務(wù)器 CPU 開銷:盡量減少數(shù)據(jù)庫排序操作以及全表查詢,減少 CPU 內(nèi)存占用。

  •  利用更多資源:使用表分區(qū),可以增加并行操作,更大限度利用 CPU 資源。

總結(jié)到 SQL 優(yōu)化中,就如下三點(diǎn):

  •  最大化利用索引。

  •  盡可能避免全表掃描。

  •  減少無效數(shù)據(jù)的查詢。

理解 SQL 優(yōu)化原理 ,首先要搞清楚 SQL 執(zhí)行順序。

SELECT 語句,語法順序如下:

1. SELECT   2. DISTINCT   3. FROM   4.  JOIN   5. ON   6. WHERE   7. GROUP BY   8. HAVING   9. ORDER BY   10.LIMIT 

SELECT 語句,執(zhí)行順序如下:

FROM  <表名> # 選取表,將多個表數(shù)據(jù)通過笛卡爾積變成一個表。  ON  <篩選條件> # 對笛卡爾積的虛表進(jìn)行篩選  JOIN     # 指定join,用于添加數(shù)據(jù)到on之后的虛表中,例如left join會將左表的剩余數(shù)據(jù)添加到虛表中  WHERE   # 對上述虛表進(jìn)行篩選  GROUP BY  <分組條件> # 分組   # 用于having子句進(jìn)行判斷,在書寫上這類聚合函數(shù)是寫在having判斷里面的  HAVING  <分組篩選> # 對分組后的結(jié)果進(jìn)行聚合篩選  SELECT  <返回數(shù)據(jù)列表> # 返回的單列必須在group by子句中,聚合函數(shù)除外  DISTINCT  # 數(shù)據(jù)除重  ORDER BY  <排序條件> # 排序  LIMIT  <行數(shù)限制>

以下 SQL 優(yōu)化策略適用于數(shù)據(jù)量較大的場景下,如果數(shù)據(jù)量較小,沒必要以此為準(zhǔn),以免畫蛇添足。

避免不走索引的場景

①盡量避免在字段開頭模糊查詢,會導(dǎo)致數(shù)據(jù)庫引擎放棄索引進(jìn)行全表掃描

如下:

SELECT * FROM t WHERE username LIKE '%陳%'

優(yōu)化方式:盡量在字段后面使用模糊查詢。

如下:

SELECT * FROM t WHERE username LIKE '陳%'

如果需求是要在前面使用模糊查詢:

  •  使用 MySQL 內(nèi)置函數(shù) INSTR(str,substr)來匹配,作用類似于 Java 中的 indexOf(),查詢字符串出現(xiàn)的角標(biāo)位置。

  •  使用 FullText 全文索引,用 match against 檢索。

  •  數(shù)據(jù)量較大的情況,建議引用 ElasticSearch、Solr,億級數(shù)據(jù)量檢索速度秒級。

  •  當(dāng)表數(shù)據(jù)量較少(幾千條兒那種),別整花里胡哨的,直接用 like '%xx%'。

②盡量避免使用 in 和 not in,會導(dǎo)致引擎走全表掃描

如下:

SELECT * FROM t WHERE id IN (2,3)

優(yōu)化方式:如果是連續(xù)數(shù)值,可以用 between 代替。

如下:

SELECT * FROM t WHERE id BETWEEN 2 AND 3

如果是子查詢,可以用 exists 代替。

如下:

-- 不走索引  select * from A where A.id in (select id from B);  -- 走索引  select * from A where exists (select * from B where B.id = A.id);

③盡量避免使用 or,會導(dǎo)致數(shù)據(jù)庫引擎放棄索引進(jìn)行全表掃描

如下:

SELECT * FROM t WHERE id = 1 OR id = 3

優(yōu)化方式:可以用 union 代替 or。

如下:

SELECT * FROM t WHERE id = 1     UNION  SELECT * FROM t WHERE id = 3

④盡量避免進(jìn)行 null 值的判斷,會導(dǎo)致數(shù)據(jù)庫引擎放棄索引進(jìn)行全表掃描

如下:

SELECT * FROM t WHERE score IS NULL

優(yōu)化方式:可以給字段添加默認(rèn)值 0,對 0 值進(jìn)行判斷。

如下:

SELECT * FROM t WHERE score = 0

⑤盡量避免在 where 條件中等號的左側(cè)進(jìn)行表達(dá)式、函數(shù)操作,會導(dǎo)致數(shù)據(jù)庫引擎放棄索引進(jìn)行全表掃描

可以將表達(dá)式、函數(shù)操作移動到等號右側(cè),如下:

-- 全表掃描  SELECT * FROM T WHERE score/10 = 9  -- 走索引  SELECT * FROM T WHERE score = 10*9

⑥當(dāng)數(shù)據(jù)量大時,避免使用 where 1=1 的條件

通常為了方便拼裝查詢條件,我們會默認(rèn)使用該條件,數(shù)據(jù)庫引擎會放棄索引進(jìn)行全表掃描。

如下:

SELECT username, age, sex FROM T WHERE 11=1

優(yōu)化方式:用代碼拼裝 SQL 時進(jìn)行判斷,沒 where 條件就去掉 where,有 where 條件就加 and。

⑦查詢條件不能用 <> 或者 !=

使用索引列作為條件進(jìn)行查詢時,需要避免使用<>或者!=等判斷條件。

如確實業(yè)務(wù)需要,使用到不等于符號,需要在重新評估索引建立,避免在此字段上建立索引,改由查詢條件中其他索引字段代替。

⑧where 條件僅包含復(fù)合索引非前置列

如下:復(fù)合(聯(lián)合)索引包含 key_part1,key_part2,key_part3 三列,但 SQL 語句沒有包含索引前置列"key_part1",按照 MySQL 聯(lián)合索引的最左匹配原則,不會走聯(lián)合索引。

select col1 from table where key_part2=1 and key_part3=2

⑨隱式類型轉(zhuǎn)換造成不使用索引

如下 SQL 語句由于索引對列類型為 varchar,但給定的值為數(shù)值,涉及隱式類型轉(zhuǎn)換,造成不能正確走索引。

select col1 from table where col_varchar=123;

⑩order by 條件要與 where 中條件一致,否則 order by 不會利用索引進(jìn)行排序

如下:

-- 不走age索引  SELECT * FROM t order by age;  -- 走age索引  SELECT * FROM t where age > 0 order by age;

對于上面的語句,數(shù)據(jù)庫的處理順序是:

  •  第一步:根據(jù) where 條件和統(tǒng)計信息生成執(zhí)行計劃,得到數(shù)據(jù)。

  •  第二步:將得到的數(shù)據(jù)排序。當(dāng)執(zhí)行處理數(shù)據(jù)(order by)時,數(shù)據(jù)庫會先查看第一步的執(zhí)行計劃,看 order by 的字段是否在執(zhí)行計劃中利用了索引。如果是,則可以利用索引順序而直接取得已經(jīng)排好序的數(shù)據(jù)。如果不是,則重新進(jìn)行排序操作。

  •  第三步:返回排序后的數(shù)據(jù)。

當(dāng) order by 中的字段出現(xiàn)在 where 條件中時,才會利用索引而不再二次排序,更準(zhǔn)確的說,order by 中的字段在執(zhí)行計劃中利用了索引時,不用排序操作。

這個結(jié)論不僅對 order by 有效,對其他需要排序的操作也有效。比如 group by 、union 、distinct 等。

?正確使用 hint 優(yōu)化語句

MySQL 中可以使用 hint 指定優(yōu)化器在執(zhí)行時選擇或忽略特定的索引。

一般而言,處于版本變更帶來的表結(jié)構(gòu)索引變化,更建議避免使用 hint,而是通過 Analyze table 多收集統(tǒng)計信息。

但在特定場合下,指定 hint 可以排除其他索引干擾而指定更優(yōu)的執(zhí)行計劃:

  •  USE INDEX 在你查詢語句中表名的后面,添加 USE INDEX 來提供希望 MySQL 去參考的索引列表,就可以讓 MySQL 不再考慮其他可用的索引。

        例子: SELECT col1 FROM table USE INDEX (mod_time, name)...

  •  IGNORE INDEX 如果只是單純的想讓 MySQL 忽略一個或者多個索引,可以使用 IGNORE INDEX 作為 Hint。

        例子: SELECT col1 FROM table IGNORE INDEX (priority) ...

  •  FORCE INDEX 為強(qiáng)制 MySQL 使用一個特定的索引,可在查詢中使用FORCE INDEX 作為 Hint。

        例子: SELECT col1 FROM table FORCE INDEX (mod_time) ...

在查詢的時候,數(shù)據(jù)庫系統(tǒng)會自動分析查詢語句,并選擇一個最合適的索引。但是很多時候,數(shù)據(jù)庫系統(tǒng)的查詢優(yōu)化器并不一定總是能使用最優(yōu)索引。

如果我們知道如何選擇索引,可以使用 FORCE INDEX 強(qiáng)制查詢使用指定的索引。

例如:

SELECT * FROM students FORCE INDEX (idx_class_id) WHERE class_id = 1 ORDER BY id DESC;

SELECT 語句其他優(yōu)化

①避免出現(xiàn) select *

首先,select * 操作在任何類型數(shù)據(jù)庫中都不是一個好的 SQL 編寫習(xí)慣。

使用 select * 取出全部列,會讓優(yōu)化器無法完成索引覆蓋掃描這類優(yōu)化,會影響優(yōu)化器對執(zhí)行計劃的選擇,也會增加網(wǎng)絡(luò)帶寬消耗,更會帶來額外的 I/O,內(nèi)存和 CPU 消耗。

建議提出業(yè)務(wù)實際需要的列數(shù),將指定列名以取代 select *。具體詳情見為什么大家都說SELECT * 效率低

②避免出現(xiàn)不確定結(jié)果的函數(shù)

特定針對主從復(fù)制這類業(yè)務(wù)場景。由于原理上從庫復(fù)制的是主庫執(zhí)行的語句,使用如 now()、rand()、sysdate()、current_user() 等不確定結(jié)果的函數(shù)很容易導(dǎo)致主庫與從庫相應(yīng)的數(shù)據(jù)不一致。

另外不確定值的函數(shù),產(chǎn)生的 SQL 語句無法利用 query cache。

③多表關(guān)聯(lián)查詢時,小表在前,大表在后

在 MySQL 中,執(zhí)行 from 后的表關(guān)聯(lián)查詢是從左往右執(zhí)行的(Oracle 相反),第一張表會涉及到全表掃描。

所以將小表放在前面,先掃小表,掃描快效率較高,在掃描后面的大表,或許只掃描大表的前 100 行就符合返回條件并 return 了。

例如:表 1 有 50 條數(shù)據(jù),表 2 有 30 億條數(shù)據(jù);如果全表掃描表 2,你品,那就先去吃個飯再說吧是吧。

④使用表的別名

當(dāng)在 SQL 語句中連接多個表時,請使用表的別名并把別名前綴于每個列名上。這樣就可以減少解析的時間并減少哪些友列名歧義引起的語法錯誤。

⑤用 where 字句替換 HAVING 字句

避免使用 HAVING 字句,因為 HAVING 只會在檢索出所有記錄之后才對結(jié)果集進(jìn)行過濾,而 where 則是在聚合前刷選記錄,如果能通過 where 字句限制記錄的數(shù)目,那就能減少這方面的開銷。

HAVING 中的條件一般用于聚合函數(shù)的過濾,除此之外,應(yīng)該將條件寫在 where 字句中。

where 和 having 的區(qū)別:where 后面不能使用組函數(shù)。

⑥調(diào)整 Where 字句中的連接順序

MySQL 采用從左往右,自上而下的順序解析 where 子句。根據(jù)這個原理,應(yīng)將過濾數(shù)據(jù)多的條件往前放,最快速度縮小結(jié)果集。

增刪改 DML 語句優(yōu)化

①大批量插入數(shù)據(jù)

如果同時執(zhí)行大量的插入,建議使用多個值的 INSERT 語句(方法二)。這比使用分開 INSERT 語句快(方法一),一般情況下批量插入效率有幾倍的差別。

方法一:

insert into T values(1,2);   insert into T values(1,3);  insert into T values(1,4);

方法二:

Insert into T values(1,2),(1,3),(1,4);

選擇后一種方法的原因有三:

  •  減少 SQL 語句解析的操作,MySQL 沒有類似 Oracle 的 share pool,采用方法二,只需要解析一次就能進(jìn)行數(shù)據(jù)的插入操作。

  •  在特定場景可以減少對 DB 連接次數(shù)。

  •  SQL 語句較短,可以減少網(wǎng)絡(luò)傳輸?shù)?IO。

②適當(dāng)使用 commit

適當(dāng)使用 commit 可以釋放事務(wù)占用的資源而減少消耗,commit 后能釋放的資源如下:

  •  事務(wù)占用的 undo 數(shù)據(jù)塊。

  •  事務(wù)在 redo log 中記錄的數(shù)據(jù)塊。

  •  釋放事務(wù)施加的,減少鎖爭用影響性能。特別是在需要使用 delete 刪除大量數(shù)據(jù)的時候,必須分解刪除量并定期 commit。

③避免重復(fù)查詢更新的數(shù)據(jù)

針對業(yè)務(wù)中經(jīng)常出現(xiàn)的更新行同時又希望獲得改行信息的需求,MySQL 并不支持 PostgreSQL 那樣的 UPDATE RETURNING 語法,在 MySQL 中可以通過變量實現(xiàn)。

例如,更新一行記錄的時間戳,同時希望查詢當(dāng)前記錄中存放的時間戳是什么?

簡單方法實現(xiàn):

Update t1 set time=now() where col1=1;   Select time from t1 where id =1;

使用變量,可以重寫為以下方式:

Update t1 set time=now () where col1=1 and @nownow: = now ();   Select @now;

前后二者都需要兩次網(wǎng)絡(luò)來回,但使用變量避免了再次訪問數(shù)據(jù)表,特別是當(dāng) t1 表數(shù)據(jù)量較大時,后者比前者快很多。

④查詢優(yōu)先還是更新(insert、update、delete)優(yōu)先

MySQL 還允許改變語句調(diào)度的優(yōu)先級,它可以使來自多個客戶端的查詢更好地協(xié)作,這樣單個客戶端就不會由于鎖定而等待很長時間。改變優(yōu)先級還可以確保特定類型的查詢被處理得更快。

我們首先應(yīng)該確定應(yīng)用的類型,判斷應(yīng)用是以查詢?yōu)橹鬟€是以更新為主的,是確保查詢效率還是確保更新的效率,決定是查詢優(yōu)先還是更新優(yōu)先。

下面我們提到的改變調(diào)度策略的方法主要是針對只存在表鎖的存儲引擎,比如  MyISAM 、MEMROY、MERGE,對于 Innodb 存儲引擎,語句的執(zhí)行是由獲得行鎖的順序決定的。

MySQL 的默認(rèn)的調(diào)度策略可用總結(jié)如下:

  •  寫入操作優(yōu)先于讀取操作。

  •  對某張數(shù)據(jù)表的寫入操作某一時刻只能發(fā)生一次,寫入請求按照它們到達(dá)的次序來處理。

  •  對某張數(shù)據(jù)表的多個讀取操作可以同時地進(jìn)行。

MySQL 提供了幾個語句調(diào)節(jié)符,允許你修改它的調(diào)度策略:

  •  LOW_PRIORITY 關(guān)鍵字應(yīng)用于 DELETE、INSERT、LOAD DATA、REPLACE 和 UPDATE。

  •  HIGH_PRIORITY 關(guān)鍵字應(yīng)用于 SELECT 和 INSERT 語句。

  •  DELAYED 關(guān)鍵字應(yīng)用于 INSERT 和 REPLACE 語句。

如果寫入操作是一個 LOW_PRIORITY(低優(yōu)先級)請求,那么系統(tǒng)就不會認(rèn)為它的優(yōu)先級高于讀取操作。

在這種情況下,如果寫入者在等待的時候,第二個讀取者到達(dá)了,那么就允許第二個讀取者插到寫入者之前。

只有在沒有其它的讀取者的時候,才允許寫入者開始操作。這種調(diào)度修改可能存在 LOW_PRIORITY 寫入操作永遠(yuǎn)被阻塞的情況。

SELECT 查詢的 HIGH_PRIORITY(高優(yōu)先級)關(guān)鍵字也類似。它允許 SELECT 插入正在等待的寫入操作之前,即使在正常情況下寫入操作的優(yōu)先級更高。

另外一種影響是,高優(yōu)先級的 SELECT 在正常的 SELECT 語句之前執(zhí)行,因為這些語句會被寫入操作阻塞。

如果希望所有支持 LOW_PRIORITY 選項的語句都默認(rèn)地按照低優(yōu)先級來處理,那么請使用--low-priority-updates 選項來啟動服務(wù)器。

通過使用 INSERTHIGH_PRIORITY 來把 INSERT 語句提高到正常的寫入優(yōu)先級,可以消除該選項對單個 INSERT 語句的影響。

查詢條件優(yōu)化

①對于復(fù)雜的查詢,可以使用中間臨時表暫存數(shù)據(jù)

②優(yōu)化 group by 語句

默認(rèn)情況下,MySQL 會對 GROUP BY 分組的所有值進(jìn)行排序,如 “GROUP BY col1,col2,....;” 查詢的方法如同在查詢中指定 “ORDER BY col1,col2,...;” 。

如果顯式包括一個包含相同的列的 ORDER BY 子句,MySQL 可以毫不減速地對它進(jìn)行優(yōu)化,盡管仍然進(jìn)行排序。

因此,如果查詢包括 GROUP BY 但你并不想對分組的值進(jìn)行排序,你可以指定 ORDER BY NULL 禁止排序。

例如:

SELECT col1, col2, COUNT(*) FROM table GROUP BY col1, col2 ORDER BY NULL ;

③優(yōu)化 join 語句

MySQL 中可以通過子查詢來使用 SELECT 語句來創(chuàng)建一個單列的查詢結(jié)果,然后把這個結(jié)果作為過濾條件用在另一個查詢中。

使用子查詢可以一次性的完成很多邏輯上需要多個步驟才能完成的 SQL 操作,同時也可以避免事務(wù)或者表鎖死,并且寫起來也很容易。但是,有些情況下,子查詢可以被更有效率的連接(JOIN)..替代。

例子:假設(shè)要將所有沒有訂單記錄的用戶取出來,可以用下面這個查詢完成:

SELECT col1 FROM customerinfo WHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo )

如果使用連接(JOIN)..來完成這個查詢工作,速度將會有所提升。

尤其是當(dāng) salesinfo 表中對 CustomerID 建有索引的話,性能將會更好,查詢?nèi)缦拢?/p>

SELECT col1 FROM customerinfo      LEFT JOIN salesinfoON customerinfo.CustomerID=salesinfo.CustomerID         WHERE salesinfo.CustomerID IS NULL

連接(JOIN)..之所以更有效率一些,是因為 MySQL 不需要在內(nèi)存中創(chuàng)建臨時表來完成這個邏輯上的需要兩個步驟的查詢工作。

④優(yōu)化 union 查詢

MySQL 通過創(chuàng)建并填充臨時表的方式來執(zhí)行 union 查詢。除非確實要消除重復(fù)的行,否則建議使用 union all。

原因在于如果沒有 all 這個關(guān)鍵詞,MySQL 會給臨時表加上 distinct 選項,這會導(dǎo)致對整個臨時表的數(shù)據(jù)做唯一性校驗,這樣做的消耗相當(dāng)高。

高效:

SELECT COL1, COL2, COL3 FROM TABLE WHERE COL1 = 10   UNION ALL   SELECT COL1, COL2, COL3 FROM TABLE WHERE COL3= 'TEST';

低效:

SELECT COL1, COL2, COL3 FROM TABLE WHERE COL1 = 10   UNION   SELECT COL1, COL2, COL3 FROM TABLE WHERE COL3= 'TEST';

⑤拆分復(fù)雜 SQL 為多個小 SQL,避免大事務(wù)

如下:

  •  簡單的 SQL 容易使用到 MySQL 的 QUERY CACHE。

  •  減少鎖表時間特別是使用 MyISAM 存儲引擎的表。

  •  可以使用多核 CPU。

⑥使用 truncate 代替 delete

當(dāng)刪除全表中記錄時,使用 delete 語句的操作會被記錄到 undo 塊中,刪除記錄也記錄 binlog。

當(dāng)確認(rèn)需要刪除全表時,會產(chǎn)生很大量的 binlog 并占用大量的 undo 數(shù)據(jù)塊,此時既沒有很好的效率也占用了大量的資源。

使用 truncate 替代,不會記錄可恢復(fù)的信息,數(shù)據(jù)不能被恢復(fù)。也因此使用 truncate 操作有其極少的資源占用與極快的時間。另外,使用 truncate 可以回收表的水位,使自增字段值歸零。

⑦使用合理的分頁方式以提高分頁效率

使用合理的分頁方式以提高分頁效率 針對展現(xiàn)等分頁需求,合適的分頁方式能夠提高分頁的效率。

案例 1:

select * from t where thread_id = 10000 and deleted = 0      order by gmt_create asc limit 0, 15;

上述例子通過一次性根據(jù)過濾條件取出所有字段進(jìn)行排序返回。數(shù)據(jù)訪問開銷=索引 IO+索引全部記錄結(jié)果對應(yīng)的表數(shù)據(jù) IO。

因此,該種寫法越翻到后面執(zhí)行效率越差,時間越長,尤其表數(shù)據(jù)量很大的時候。

適用場景:當(dāng)中間結(jié)果集很?。?0000 行以下)或者查詢條件復(fù)雜(指涉及多個不同查詢字段或者多表連接)時適用。

案例 2:

select t.* from (select id from t where thread_id = 10000 and deleted = 0     order by gmt_create asc limit 0, 15) a, t         where a.id = t.id;

上述例子必須滿足 t 表主鍵是 id 列,且有覆蓋索引 secondary key:(thread_id, deleted, gmt_create)。

通過先根據(jù)過濾條件利用覆蓋索引取出主鍵 id 進(jìn)行排序,再進(jìn)行 join 操作取出其他字段。

數(shù)據(jù)訪問開銷=索引 IO+索引分頁后結(jié)果(例子中是 15 行)對應(yīng)的表數(shù)據(jù) IO。因此,該寫法每次翻頁消耗的資源和時間都基本相同,就像翻第一頁一樣。

適用場景:當(dāng)查詢和排序字段(即 where 子句和 order by 子句涉及的字段)有對應(yīng)覆蓋索引時,且中間結(jié)果集很大的情況時適用。

建表優(yōu)化

①在表中建立索引,優(yōu)先考慮 where、order by 使用到的字段。

②盡量使用數(shù)字型字段(如性別,男:1 女:2),若只含數(shù)值信息的字段盡量不要設(shè)計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。

這是因為引擎在處理查詢和連接時會 逐個比較字符串中每一個字符,而對于數(shù)字型而言只需要比較一次就夠了。

③查詢數(shù)據(jù)量大的表 會造成查詢緩慢。主要的原因是掃描行數(shù)過多。這個時候可以通過程序,分段分頁進(jìn)行查詢,循環(huán)遍歷,將結(jié)果合并處理進(jìn)行展示。

要查詢 100000 到 100050 的數(shù)據(jù),如下:

SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY ID ASC) AS rowid,*      FROM infoTab)t WHERE t.rowid > 100000 AND t.rowid <= 100050

④用 varchar/nvarchar 代替 char/nchar。

盡可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長字段存儲空間小,可以節(jié)省存儲空間,其次對于查詢來說,在一個相對較小的字段內(nèi)搜索效率顯然要高些。

不要以為 NULL 不需要空間,比如:char(100) 型,在字段建立時,空間就固定了, 不管是否插入值(NULL 也包含在內(nèi)),都是占用 100 個字符的空間的,如果是 varchar 這樣的變長字段, null 不占用空間。

到此,相信大家對“MySQL優(yōu)化技巧有哪些”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


網(wǎng)站名稱:MySQL優(yōu)化技巧有哪些
分享URL:http://weahome.cn/article/jdcoih.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部