Mysql中select的正確姿勢
大家在開發中,還有很多童鞋在寫查詢語句的時候,習慣寫下面這種不規範sql
select * from table
而不寫成下面的這種規範方式
select col1,col2,...,coln from table
我也知道,這些童鞋是圖方便,畢竟再敲一堆的列名,嫌麻煩!
你們上班可以問問自己的同事
你:“xx,知道select *和select所有欄位的區別麼?
同事:"額。。額。。額。。"
留下的只有尷尬的笑容!
我也知道,很多人至今都沒有搞懂select *和selct 所有欄位的區別
因此,我開一文來說明一下。另外,我選的是自己最熟悉的mysql資料庫,此文的結論在oralce,sqlserver上是否成立,博主沒做過測試。
正文
(select所有欄位)效能高?
網路上流傳著一種說法說是
“*” 表示通配所有欄位,在SQL的機制裡,需要先識別統計所有欄位再進行下一步。
明確指定欄位的話,會減少上述的操作,所以效率有所提升。
然而,實際上呢?效率是相差不大的!。
取部落格
http://flysnowxf.iteye.com/blog/1125032
的測試結果
mysql 5.1.37
表記錄數41,547,002,即4000w行
使用遠端客戶端取1000條資料,統計時間:
SELECT * FROM `dmsp`.`dmsp_dimension_content` LIMIT 0, 1000;
時間2.218s,網路消耗0.547s
SELECT `id`, `appid`, `aop`, `t`, `uid`, `sid`, `pid`, `pname`, `bid`, `bname`, `ptype`, `sm`, `sv`, `bt`, `national`, `area`, `ov` FROM `dmsp`.`dmsp_dimension_content` LIMIT 0, 1000;
取出所有欄位,時間2.250s,網路消耗0.578s
可以看出,這二者的時間差幾乎可以忽略,另外還有一本書上的內容也可以佐證我的話。
《SQL CookBook》第一章 檢索記錄中1.1小節(原書第十五頁內容如下):
image
此書也說明了,兩種方式在效能上幾乎是沒有差距的。
那為什麼還是不推薦select * ?
網路IO問題
很多文章裡說什麼,會帶來額外的記憶體、磁碟、cpu的開銷。對此,我有自己的觀點。我覺得這不是主要原因。主要原因是帶來了額外的網路開銷。
在一個系統中,記憶體、磁碟、cpu的開銷,不過是微妙級。造成系統的延遲的重頭戲是網路開銷。網路開銷可能帶來秒級的延遲。當然,如果你的應用程式和資料庫是在同一臺機器上的,那當我沒說這句話!
select *會查詢出不需要的、額外的資料,那麼這些額外的資料在網路上進行傳輸,必定會造成效能延遲。假設你的table中,有一個列的型別為binary。此時,你的select *操作,就會十分緩慢,並且會造成額外的網路開銷。
索引問題
仔細看下面的兩句sql
select col1 from table;
select * from table;
如果col1欄位包含索引資訊,那麼此時,這兩句的sql執行時間可能會有幾十上百倍的差異。
在col1欄位有索引的情況下,mysql是可以不用讀data,直接使用index裡面的值就返回結果的。但是一旦用了select *,就會有其他列需要讀取,這時在讀完index以後還需要去讀data才會返回結果。這樣就造成了額外的效能開銷。
ps:我不想在這裡扯什麼覆蓋索引,輔助索引的概念。其實要講的很專業,扯一堆高大上的名詞,我也可以。只是這樣徒增讀者的理解難度,儘量用通俗的方式來講。
擴充套件性問題
有的人會覺得
使用select * ,這樣在增加列的時候,不用改sql,方便!
然而實際上,你的sql是不用改了,但是對你的程式程式碼是有很大的影響的!
身為一名21世紀的優良程式設計師,我們是不能獲取自己需要的東西的!你因為一時高興,執行了select *,如果增加或刪除列,會對你的程式碼有著極大的影響。
反過來,如果你select 指定列,只獲取自己需要的幾列,表結構的修改,對你程式碼的影響就會小很多。相比之下,風險就沒有那麼大了!
另外就是,對於其他人接手你專案的人來說,看到select 指定列的方式,可讀性更強,對於他們來說更好上手!
E:\app\Administrator www.ysyl157.com admin\orcl\dpdump
2、建立使用者
create user testdb65 identified by “testdb65”
default tablespace users temporary tablespace temp;
使用者授權
grant connect,dba to testdb65;
3、建立表空間
CREATE TABLESPACE HR_DATA01 DATAFILE ‘D:\nhsj\hr_data01.dbf’ SIZE 500M AUTOEXTEND ON NEXT 50M EXTENT MANAGEMENT LOCAL UNIFORM SIZE 256K ; 【建立表空間】
4、匯入 bgyhr2是來源庫
impdp testdb65/
匯出 scott 是要匯出的庫
expdp lfwtrain/[email protected] schema=當前使用者 dumpfile=expdptest.dmp
(18)重導dmp檔案
Oracle儲存資料時一般以DMP檔案的形式進行儲存
本部落格記錄,DMP檔案的匯入 先開啟CMD
sqlplus /nolog
以sysdba連線
conn /as sysdba
這裡建立表空間,因為表空間進行儲存的話,可以提供系統性能
CREATE TABLESPACE DATA01 DATAFILE 'D:\tablespace\data01.dbf' SIZE 100M AUTOEXTEND ON NEXT 50M EXTENT MANAGEMENT LOCAL UNIFORM SIZE 256K ;
建立使用者
CREATE USER job IDENTIFIED BY job DEFAULT TABLESPACE DATA01 TEMPORARY TABLESPACE TEMP QUOTA UNLIMITED ON DATA01
授權
grant connect,dba to job;
複製dmp檔案到oracle安裝目錄裡的app\admin\orce\dpdump裡,然後用以下程式碼匯入dmp檔案,要順便匯入logfile的話,加上logfile=檔名
impdp job/
(19)vm_concat函式
函式wm_concat(列名),該函式可以把列值以","號分隔起來,並顯示成一行
ps:這個列轉行函式vm_comcat(www.yinmaoyule178.com)在oracle10比較穩定,到了oracle11就會出現一些不相容的情況,oracle12版本就沒這個函數了
(20)replace函式
REPLACE(char, search_string [, replacement_string ] )
char : 等待替換的字串
search_string : 搜尋需要替換的字串
replacement_string : 替換字串
如果replacement_string預設或者為null,那麼所有char中出現的search_string 都將被移除
如果search_string為null,那麼結果就是char
例子:過濾某個欄位的換行符
select replace(a, chr(10)) from tableA
1
(21) instr函式
格式一:instr(www.ylouyi3.com string1, string2 ) / instr(源字串, 目標字串)
格式二:instr( string1, string2 [, start_position [, nth_appearance ] ] ) / instr(源字串, 目標字串, 起始位置, 匹配序號)
解析:string2 的值要在string1中查詢,是從start_position給出的數值(即:位置)開始在string1檢索,檢索第nth_appearance(幾)次出現string2。
例子:查詢某個資料欄位是否包含換行符
select * from tableA where instr(a,chr(10))>0