教你精確編寫高質量高性能的MySQL語法

在應用系統開發初期,由于開發數據庫數據比較少,對于查詢SQL語句,復雜視圖的編寫,剛開始不會體會出SQL語句各種寫法的性能優劣,但是如果將應用系統提交實際應用后,隨著數據庫中數據的增加,系統的響應速度就成為目前系統需要解決的最主要的問題之一。系統優化中一個很重要的方面就是SQL語句的優化。對于海量數據,劣質SQL語句和優質SQL語句之間的速度差別可達到上百倍,可見對于一個系統不是簡單的能實現其功能就可以了,而是要寫出高質量的SQL語句,提高系統的可用性。

在多數情況下,Oracle使用索引來更快的遍歷表,優化器主要根據定義的索引來提高性能。但是,如果在SQL語句的where子句中寫的SQL代碼不合理,就會造成優化器刪去索引而使用全表掃描,一般就這種SQL語句,被稱為劣質的SQL語句。在編寫SQL語句時我們應清楚優化器根據何種原則來刪除索引,這有助于寫出高性能之SQL語句。

下面就某些SQL語句的where子句編寫中需要注意的問題作詳細介紹。在這些where子句中,即使某些列存在索引,但是由于編寫了劣質的SQL,系統在運行該SQL語句時也不能使用該索引,而同樣使用全表掃描,這就造成了響應速度之極大降低。

1. IS NULL 與 IS NOT NULL

不能用null作索引,任何包含null值的列都將不會被包含在索引中。即使索引有多列這樣之情況下,只要這些列中有一列含有null,該列就會從索引中排除。也就是說如果某列存在空值,即使對該列建索引也不會提高性能。

任何在where子句中使用is null或is not null的語句優化器是不允許使用索引的。

2. 聯接列

對于有聯接的列,即使最后的聯接值為一個靜態值,優化器是不會使用索引的。我們一起來看一個例子,假定有一個職工表(employee),對于一個職工之姓和名分成兩列存放(FIRST_NAME和LAST_NAME),現在要查詢一個叫比爾.克林頓(Bill Cliton)的職工。

下面是一個采用聯接查詢的SQL語句,

上面這條語句完全可以查詢出是否有Bill Cliton這個員工,但是這里需要注意,系統優化器對基于last_name創建的索引沒有使用。

當采用下面這種SQL語句來編寫,Oracle系統就可以采用基于last_name創建的索引。

遇到下面這種情況又如何處理呢?如果一個變量(name)中存放著Bill Cliton這個員工之姓名,對于這種情況我們又如何避免全程遍歷,使用索引呢?可以使用一個函數,將變量name中的姓和名分開就可以了,但是有一點需要注意,這個函數是不能作用在索引列上。下面是SQL查詢腳本:

3. 帶通配符(%)的like語句

同樣以上面的例子來看這種情況。目前的需求是這樣的,要求在職工表中查詢名字中包含cliton的人。可以采用如下的查詢SQL語句:

這里由于通配符(%)在搜尋詞首出現,所以Oracle系統不使用last_name的索引。在很多情況下可能無法避免這種情況,但是一定要心中有底,通配符如此使用會降低查詢速度。然而當通配符出現在字符串其他位置時,優化器就能利用索引。


4. Order by語句

ORDER BY語句決定了Oracle如何將返回的查詢結果排序。Order by語句對要排序的列沒有什么特別的限制,也可以將函數加入列中(象聯接或者附加等)。任何在Order by語句的非索引項或者有計算表達式都將降低查詢速度。

仔細檢查order by語句以找出非索引項或者表達式,它們會降低性能。解決這個問題的辦法就是重寫order by語句以使用索引,也可以為所使用的列建立另外一個索引,同時應絕對避免在order by子句中使用表達式。

5. NOT

我們在查詢時經常在where子句使用一些邏輯表達式,如大于、小于、等于以及不等于等等,也可以使用and(與)、or(或)以及not(非)。NOT可用來對任何邏輯運算符號取反。

如果要使用NOT,則應在取反的短語前面加上括號,并在短語前面加上NOT運算符。NOT運算符包含在另外一個邏輯運算符中,這就是不等于(<>)運算符。換句話說,即使不在查詢where子句中顯式的加入NOT詞,NOT仍在運算符中。

對這個查詢,可以改寫為不使用NOT:

雖然這兩種查詢之結果一樣,但是第二種查詢方案會比第一種查詢方案更快些。第二種查詢允許Oracle對salary列使用索引,而第一種查詢則不能使用索引。

6. IN和EXISTS

有時候會將一列和一系列值相比較。最簡單的辦法就是在where子句中使用子查詢。在where子句中可以使用兩種格式的子查詢。

第一種格式是使用IN操作符;第二種格式是使用EXIST操作符。

我相信絕大多數人會使用第一種格式,因為它比較容易編寫,而實際上第二種格式要遠比第一種格式的效率高。在Oracle中可以幾乎將所有的IN操作符子查詢改寫為使用EXISTS的子查詢。

第二種格式中,子查詢以‘select 'X'開始。運用EXISTS子句不管子查詢從表中抽取什么數據它只查看where子句。這樣優化器就不必遍歷整個表而僅根據索引就可完成工作(這里假定在where語句中使用的列存在索引)。相對于IN子句來說,EXISTS使用相連子查詢,構造起來要比IN子查詢困難一些。

通過使用EXIST,Oracle系統會首先檢查主查詢,然后運行子查詢直到它找到第一個匹配項,這就節省了時間。Oracle系統在執行IN子查詢時,首先執行子查詢,并將獲得的結果列表存放在在一個加了索引的臨時表中。在執行子查詢之前,系統先將主查詢掛起,待子查詢執行完畢,存放在臨時表中以后再執行主查詢。這也就是使用EXISTS比使用IN通常查詢速度快的原因。

同時應盡可能使用NOT EXISTS來代替NOT IN,盡管二者都使用了NOT(不能使用索引而降低速度),NOT EXISTS要比NOT IN查詢效率更高。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/535715.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/535715.shtml
英文地址,請注明出處:http://en.pswp.cn/news/535715.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Docker使用-Hello World

1、docker pull hello-world 拉去docker遠程倉庫中的Hello World的鏡像 [rootCarlota2 ~]# docker pull hello-world Using default tag: latest latest: Pulling from library/hello-world 0e03bdcc26d7: Pull complete Digest: sha256:7f0a9f93b4aa3022c3a4c147a449bf11e09…

Mysql數據庫引擎快速指南

如果你是個賽車手并且按一下按鈕就能夠立即更換引擎而不需要把車開到車庫里去換&#xff0c;那會是怎么感覺呢&#xff1f; MySQL 數據庫為開發人員所做的就好像是按按鈕換引擎&#xff1b;它讓你選擇數據庫引擎&#xff0c;并給你一條簡單的途徑來切換它。 MySQL的自帶引擎肯…

Docker使用-構建MySQL

拉取官方鏡像&#xff08;我們這里選擇5.7&#xff0c;如果不寫后面的版本號則會自動拉取最新版&#xff09; docker pull mysql:5.7 # 拉取 mysql 5.7 docker pull mysql # 拉取最新版mysql鏡像MySQL文檔地址 檢查是否拉取成功 $ sudo docker images一般來說數據庫容…

Java集合:什么是Java集合?

一、集合的由來 通常&#xff0c;我們的Java程序需要根據程序運行時才知道創建了多少個對象。但若非程序運行&#xff0c;程序開發階段&#xff0c;我們根本不知道到底需要多少個數量的對象&#xff0c;甚至不知道它的準確類型。為了滿足這些常規的編程需要&#xff0c;我們要…

Mysql截取中英數混合的字符串

在 mysql中截取字符串我們用 LEFT函數 LEFT(str,len) 返回從字符串str 開始的len 最左字符。 mysql> SELECT LEFT(foobarbar, 5); -> fooba 手冊上只介紹了截取英文字符串的方法&#xff0c;中文或者中英文的怎么辦呢&#xff1f;以下是截取中英混合的字符串(中國人…

Java集合:Collection接口

Collection是一個接口&#xff0c;繼承自Iterable。我們先看一下Iterable接口的源碼 一、Iterable package java.lang;import java.util.Iterator; import java.util.Objects; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Cons…

Java集合:List集合

List集合 List集合類中元素有序、且可重復&#xff0c;集合中的每個元素都有其對應的順序索引。 List容器中的元素都對應一個整數型的序號記載其在容器中的位置&#xff0c;可以根據序號存取容器中的元素。 JDK API中List接口的實現類常用的有&#xff1a;ArrayList、LinkList和…

MySQL為什么要set names

大家都知道SET NAMES x相當于SET character_set_client x;SET character_set_results x;SET character_set_connection x; 以下從MySQL5.0官方文檔上摘錄了相關內容&#xff0c;并翻譯&#xff0c;說明了相關系統變量的用處&#xff1a; What character set is the statem…

MySql日期處理系列-常用的日期推算處理

以下都是我平時用的一些日期推算處理方法&#xff0c;方法并不一定是最有效率的.全部均通過測試!轉載請注明來自[phpchina.com] #title: 常用的日期推算處理#auther: 小強(占卜師) #date: 2007-12-25 #取得當前日期set dtCURDATE();select dt; #當前日期這個月的第一天selec…

Java集合:Set集合

一、Set接口的特點 一個不包含重復元素的collection。更確切地講&#xff0c;Set不包含滿足e1.equals(e2)的元素對 e1和e2&#xff0c;并且最多包含一個null元素。 Set集合由Set接口和Set接口的實現類組成&#xff0c;Set接口繼承了Collection接口&#xff0c;因此包含了Coll…

談談我對MYSQL亂碼的解決辦法

經常更換虛擬主機,而各個服務商的MYSQL版本不同,當導入數據后,總會出現亂碼等無法正常顯示的問題,查了好多資料,總結出自己的一點技巧: WINDOWS 下導入應該這樣使用MYSQL的命令在DOS命令下進入mysql的bin目錄下,輸入mysql -uroot -p密碼 數據庫名稱<要恢復的數據庫, 例如我們…

Java集合:Map集合

一、簡述 public interface Map<K,V>將鍵映射到值的對象。一個映射不能包含重復的鍵&#xff1b;每個鍵最多只能映射到一個值。 注意&#xff1a;Map中的集合不能包含重復的鍵&#xff0c;值可以重復。每個鍵只能對應一個值。 Map集合是鍵值對形式存儲值的&#xff0c…

用離線編輯器Zoundry寫zblog日志

Zoundry是免費的離線網志發布工具&#xff0c;由于家里的網絡很差&#xff0c;寫了一半的日志經常因為掉線而丟失&#xff0c;這樣一款軟件的確是很必要的。今天下載試用了一下&#xff0c;感覺的確不錯。使用起來也很簡單&#xff1a; 1.下載并安裝zoundry軟件&#xff1a;現…

MySQL:基本命令

一、數據庫操作 1、查詢數據庫&#xff0c;命令如下: SHOW DATABASES;2、我們可以在登陸 MySQL 服務后&#xff0c;使用 create 命令創建數據庫&#xff0c;命令格式: CREATE DATABASE 數據庫名;3、使用 drop 命令刪除數據庫&#xff0c;命令格式&#xff1a; drop databas…

CentOS 5打造全功能Web服務器

轉&#xff1a;主要做為歷史記錄&#xff0c;以后用。另外很少見這么好的編譯的文章&#xff0c;其實我不推薦用編譯安裝。但這個文章不錯.V3.0 2007年11月11日 將搭建教程劃分階段以適應不同需要。加入程序優化&#xff0c;程序安全&#xff0c;加入memcache&#xff0c;squid…

MySQL:查詢條件

查詢條件 1、使用 WHERE 子句從數據表中讀取數據的通用語法&#xff1a; SELECT field1, field2,...fieldN FROM table_name1, table_name2... [WHERE condition1 [AND [OR]] condition2.....查詢語句中你可以使用一個或者多個表&#xff0c;表之間使用逗號**,** 分割&#x…

linux下的ImageMagick安裝

檢查系統有無安裝ImageMagick官方網址是&#xff1a; www.imagemagick.org 從官方不好下載&#xff0c;提供 sourceforge的下載地址&#xff1a; imagemagick.sourceforge.net shell> rpm -qa | grep ImageMagick 沒有就開始安裝ImageMagickshell> rpm -Uvh ImageMagi…

MySQL:進階應用

一、進階應用 1、可以在 SELECT, UPDATE 和 DELETE 語句中使用 Mysql 的 JOIN 來聯合多表查詢。 JOIN 按照功能大致分為如下三類&#xff1a; INNER JOIN&#xff08;內連接,或等值連接&#xff09;&#xff1a;獲取兩個表中字段匹配關系的記錄。**LEFT JOIN&#xff08;左連…

Hive-常用操作

一. 數據庫操作 1、創建數據庫 //用戶可以用 IF NOT EXISTS 選項來忽略這個異常。create database [ if not exists ] myhive ;2、創建數據庫并指定hdfs存儲位置 create database myhive2 location /myhive2;3、修改數據庫&#xff0c;可以使用alter database 命令來修改數據…

linux下nmap工具的使用

nmap NMap&#xff0c;也就是Network Mapper&#xff0c;是Linux下的網絡掃描和嗅探工 具包&#xff0c;其基本功能有三個&#xff0c;一是探測一組主機是否在線&#xff1b;其次是掃描主機端口&#xff0c;嗅探所提供的網絡服務&#xff1b;還可以推斷主機所用的操作系統 。N…