這個(gè)提示的意思是沒選擇數(shù)據(jù)庫。
創(chuàng)新互聯(lián)專注于樺南網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠為您提供樺南營銷型網(wǎng)站建設(shè),樺南網(wǎng)站制作、樺南網(wǎng)頁設(shè)計(jì)、樺南網(wǎng)站官網(wǎng)定制、重慶小程序開發(fā)公司服務(wù),打造樺南網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供樺南網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。
如果你是使用軟件(如navicat、SQL yog等)來創(chuàng)建數(shù)據(jù)庫的話,先點(diǎn)一下軟件左邊的數(shù)據(jù)庫名稱,選中要?jiǎng)?chuàng)建的表所屬數(shù)據(jù)庫,再新建表。
如果是使用命令行創(chuàng)建,則先執(zhí)行命令:use 數(shù)據(jù)庫名;(如在test數(shù)據(jù)庫中創(chuàng)建表,則輸入:use test;后按回車)
問題
我們有一個(gè) SQL,用于找到?jīng)]有主鍵 / 唯一鍵的表,但是在 MySQL 5.7 上運(yùn)行特別慢,怎么辦?
實(shí)驗(yàn)
我們搭建一個(gè) MySQL 5.7 的環(huán)境,此處省略搭建步驟。
寫個(gè)簡單的腳本,制造一批帶主鍵和不帶主鍵的表:
執(zhí)行一下腳本:
現(xiàn)在執(zhí)行以下 SQL 看看效果:
...
執(zhí)行了 16.80s,感覺是非常慢了。
現(xiàn)在用一下 DBA 三板斧,看看執(zhí)行計(jì)劃:
感覺有點(diǎn)慘,由于 information_schema.columns 是元數(shù)據(jù)表,沒有必要的統(tǒng)計(jì)信息。
那我們來 show warnings 看看 MySQL 改寫后的 SQL:
我們格式化一下 SQL:
可以看到 MySQL 將
select from A where A.x not in (select x from B) //非關(guān)聯(lián)子查詢
轉(zhuǎn)換成了
select from A where not exists (select 1 from B where B.x = a.x) //關(guān)聯(lián)子查詢
如果我們自己是 MySQL,在執(zhí)行非關(guān)聯(lián)子查詢時(shí),可以使用很簡單的策略:
select from A where A.x not in (select x from B where ...) //非關(guān)聯(lián)子查詢:1. 掃描 B 表中的所有記錄,找到滿足條件的記錄,存放在臨時(shí)表 C 中,建好索引2. 掃描 A 表中的記錄,與臨時(shí)表 C 中的記錄進(jìn)行比對(duì),直接在索引里比對(duì),
而關(guān)聯(lián)子查詢就需要循環(huán)迭代:
select from A where not exists (select 1 from B where B.x = a.x and ...) //關(guān)聯(lián)子查詢掃描 A 表的每一條記錄 rA: ? ? 掃描 B 表,找到其中的第一條滿足 rA 條件的記錄。
顯然,關(guān)聯(lián)子查詢的掃描成本會(huì)高于非關(guān)聯(lián)子查詢。
我們希望 MySQL 能先"緩存"子查詢的結(jié)果(緩存這一步叫物化,MATERIALIZATION),但MySQL 認(rèn)為不緩存更快,我們就需要給予 MySQL 一定指導(dǎo)。
...
可以看到執(zhí)行時(shí)間變成了 0.67s。
整理
我們?cè)\斷的關(guān)鍵點(diǎn)如下:
\1. 對(duì)于 information_schema 中的元數(shù)據(jù)表,執(zhí)行計(jì)劃不能提供有效信息。
\2. 通過查看 MySQL 改寫后的 SQL,我們猜測(cè)了優(yōu)化器發(fā)生了誤判。
\3. 我們?cè)黾恿?hint,指導(dǎo) MySQL 正確進(jìn)行優(yōu)化判斷。
但目前我們的實(shí)驗(yàn)僅限于猜測(cè),猜中了萬事大吉,猜不中就無法做出好的診斷。
MySQL 數(shù)據(jù)庫的varchar類型在4.1以下的版本中的最大長度限制為255,其數(shù)據(jù)范圍可以是0~255或1~255(根據(jù)不同版本數(shù)據(jù)庫來定)。在 MySQL5.0以上的版本中,varchar數(shù)據(jù)類型的長度支持到了65535,也就是說可以存放65532個(gè)字節(jié)的數(shù)據(jù),起始位和結(jié)束位占去了3個(gè)字 節(jié),也就是說,在4.1或以下版本中需要使用固定的TEXT或BLOB格式存放的數(shù)據(jù)可以使用可變長的varchar來存放,這樣就能有效的減少數(shù)據(jù)庫文 件的大小。
MySQL 數(shù)據(jù)庫的varchar類型在4.1以下的版本中,nvarchar(存儲(chǔ)的是Unicode數(shù)據(jù)類型的字符)不管是一個(gè)字符還是一個(gè)漢字,都存為2個(gè)字節(jié) ,一般用作中文或者其他語言輸入,這樣不容易亂碼 ;varchar: 漢字是2個(gè)字節(jié),其他字符存為1個(gè)字節(jié) ,varchar適合輸入英文和數(shù)字。
4.0版本以下,varchar(20),指的是20字節(jié),如果存放UTF8漢字時(shí),只能存6個(gè)(每個(gè)漢字3字節(jié)) ;5.0版本以上,varchar(20),指的是20字符,無論存放的是數(shù)字、字母還是UTF8漢字(每個(gè)漢字3字節(jié)),都可以存放20個(gè),最大大小是65532字節(jié) ;varchar(20)在Mysql4中最大也不過是20個(gè)字節(jié),但是Mysql5根據(jù)編碼不同,存儲(chǔ)大小也不同,具體有以下規(guī)則:
a) 存儲(chǔ)限制
varchar 字段是將實(shí)際內(nèi)容單獨(dú)存儲(chǔ)在聚簇索引之外,內(nèi)容開頭用1到2個(gè)字節(jié)表示實(shí)際長度(長度超過255時(shí)需要2個(gè)字節(jié)),因此最大長度不能超過65535。
b) 編碼長度限制
字符類型若為gbk,每個(gè)字符最多占2個(gè)字節(jié),最大長度不能超過32766;
字符類型若為utf8,每個(gè)字符最多占3個(gè)字節(jié),最大長度不能超過21845。
若定義的時(shí)候超過上述限制,則varchar字段會(huì)被強(qiáng)行轉(zhuǎn)為text類型,并產(chǎn)生warning。
c) 行長度限制
導(dǎo)致實(shí)際應(yīng)用中varchar長度限制的是一個(gè)行定義的長度。 MySQL要求一個(gè)行的定義長度不能超過65535。若定義的表長度超過這個(gè)值,則提示
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs。