interview-db
索引就一種特殊的查詢表,數(shù)據(jù)庫的搜索可以利用它加速對數(shù)據(jù)的檢索。它很類似與現(xiàn)實生活中書的目錄,不需要查詢整本書內(nèi)容就可以找到想要的數(shù)據(jù)。索引可以是唯一的,創(chuàng)建索引允許指定單個列或者是多個列。缺點是它減慢了數(shù)據(jù)錄入的速度,同時也增加了數(shù)據(jù)庫的尺寸大小。
2.什么字段適合建索引
唯一性比較高,不為空,經(jīng)常查詢
3.常見慢查詢優(yōu)化
1.建索引 2.減少表之間的關(guān)聯(lián) 3.優(yōu)化sql,盡量讓sql很快定位數(shù)據(jù),不要讓sql做全表查詢,應(yīng)該走索引,把數(shù)據(jù) 量大的表排在前面 4.簡化查詢字段,沒用的字段不要,已經(jīng)對返回結(jié)果的控制,盡量返回少量數(shù)據(jù) 5.盡量用PreparedStatement來查詢,不要用Statement
4.truncate,delete 和 drop
TRUNCATE TABLE 在功能上與不帶 WHERE 子句的 DELETE 語句相同:二者均刪除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系統(tǒng)和事務(wù)日志資源少。 DELETE 語句每次刪除一行,并在事務(wù)日志中為所刪除的每行記錄一項。
TRUNCATE TABLE 通過釋放存儲表數(shù)據(jù)所用的數(shù)據(jù)頁來刪除數(shù)據(jù),并且只在事務(wù)日志中記錄頁的釋放。?
TRUNCATE TABLE 刪除表中的所有行,但表結(jié)構(gòu)及其列、約束、索引等保持不變。新行標(biāo)識所用的計數(shù)值重置為該列的種子。如果想保留標(biāo)識計數(shù)值,請改用 DELETE。如果要刪除表定義及其數(shù)據(jù),請使用 DROP TABLE 語句。
TRUNCATE,DELETE,DROP 放在一起比較:
TRUNCATE TABLE :刪除內(nèi)容、釋放空間但不刪除定義。DELETE TABLE: 刪除內(nèi)容不刪除定義,不釋放空間。
DROP TABLE :刪除內(nèi)容和定義,釋放空間。
5.列舉幾種表連接方式,有什么區(qū)別
左連接、右連接、全連接、 內(nèi)連接:只有兩個元素表相匹配的才能在結(jié)果集中顯示。 左外連接:左邊為驅(qū)動表,驅(qū)動表的數(shù)據(jù)全部顯示,匹配表的不匹配的不會顯示。 右外連接:右邊為驅(qū)動表,驅(qū)動表的數(shù)據(jù)全部顯示,匹配表的不匹配的不會顯示。 全外連接:連接的表中不匹配的數(shù)據(jù)全部會顯示出來。 交叉連接: 笛卡爾效應(yīng),顯示的結(jié)果是鏈接表數(shù)的乘積。
6.索引最左原則
SHOW INDEX FROM employees.titles;
+--------+------------+----------+--------------+-------------+-----------+-------------+------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Null | Index_type |
+--------+------------+----------+--------------+-------------+-----------+-------------+------+------------+
| titles | 0 | PRIMARY | 1 | emp_no | A | NULL | | BTREE |
| titles | 0 | PRIMARY | 2 | title | A | NULL | | BTREE |
| titles | 0 | PRIMARY | 3 | from_date | A | 443308 | | BTREE |
| titles | 1 | emp_no | 1 | emp_no | A | 443308 | | BTREE |
+--------+------------+----------+--------------+-------------+-----------+-------------+------+------------+
6.1,索引是否有問題?
從結(jié)果中可以到titles表的主索引為<emp_no, title, from_date>,還有一個輔助索引<emp_no>。為了避免多個索引使事情變復(fù)雜(MySQL的SQL優(yōu)化器在多索引時行為比較復(fù)雜),這里我們將輔助索引drop掉:
6.2,全列匹配
全列匹配(此時若沒有按照索引順序時,mysql查詢優(yōu)化器會自動的調(diào)整順序來使用定義好的索引)
6.3,最左前綴匹配
SELECT * FROM employees.titles WHERE emp_no='10001';
SELECT * FROM employees.titles WHERE emp_no='10001' AND from_date='1986-06-26';
上面的sql是否用到了索引.
6.4 上面6.3中的第二個sql可以優(yōu)化一下嗎?
優(yōu)化方法可以窮舉索引第二列,如果第二列數(shù)據(jù)有限;或者增加輔助索引<emp_no, from_date>.
SELECT * FROM employees.titles
WHERE emp_no='10001'
AND title IN ('Senior Engineer', 'Staff', 'Engineer', 'Senior Staff', 'Assistant Engineer', 'Technique Leader', 'Manager')
AND from_date='1986-06-26';
6.5 模糊匹配與索引
SELECT * FROM employees.titles WHERE emp_no='10001' AND title LIKE 'Senior%';
6.6 范圍查詢
SELECT * FROM employees.titles WHERE emp_no < '10010' and title='Senior Engineer';
(范圍查詢后面的列將無法使用索引)
范圍列可以用到索引(必須是最左前綴),但是范圍列后面的列無法用到索引。同時,索引最多用于一個范圍列,因此如果查詢條件中有兩個范圍列則無法全用到索引。
6.7 查詢條件中含有函數(shù)或表達式
很不幸,如果查詢條件中含有函數(shù)或表達式,則MySQL不會為這列使用索引(雖然某些在數(shù)學(xué)意義上可以使用)。例如
SELECT * FROM employees.titles WHERE emp_no='10001' AND left(title, 6)='Senior';
SELECT * FROM employees.titles WHERE emp_no - 1='10000';
7. exist 和 in
select * from A where id in(select id from B)
A表比B表大的情況,效率較好;如果a表的id有索引,會被利用到.
select a.* from A a where exists(select 1 from B b where a.id=b.id)
exists()適合B表比A表數(shù)據(jù)大的情況,如果b.id有索引會被利用到.
當(dāng)A表數(shù)據(jù)與B表數(shù)據(jù)一樣大時,in與exists效率差不多,可結(jié)合索引情況使用.
in 和 exists的區(qū)別: 如果子查詢得出的結(jié)果集記錄較少,主查詢中的表較大且又有索引時應(yīng)該用in, 反之如果外層的主查詢記錄較少,子查詢中的表大,又有索引時使用exists。其實我們區(qū)分in和exists主要是造成了驅(qū)動順序的改變(這是性能變化的關(guān)鍵),如果是exists,那么以外層表為驅(qū)動表,先被訪問,如果是IN,那么先執(zhí)行子查詢,所以我們會以驅(qū)動表的快速返回為目標(biāo),那么就會考慮到索引及結(jié)果集的關(guān)系了 ,另外IN時不對NULL進行處理。
in 是把外表和內(nèi)表作hash 連接,而exists是對外表作loop循環(huán),每次loop循環(huán)再對內(nèi)表進行查詢。一直以來認(rèn)為exists比in效率高的說法是不準(zhǔn)確的。
8.mysql數(shù)據(jù)庫引擎MyISAM和InnoDB的區(qū)別
8.1、存儲結(jié)構(gòu)?
每個MyISAM在磁盤上存儲成三個文件。第一個文件的名字以表的名字開始,擴展名指出文件類型。?
.frm文件存儲表定義。?
數(shù)據(jù)文件的擴展名為.MYD (MYData)。?
索引文件的擴展名是.MYI (MYIndex)。
8.2、存儲空間?
MyISAM:可被壓縮,存儲空間較小。?
InnoDB:需要更多的內(nèi)存和存儲,它會在主內(nèi)存中建立其專用的緩沖池用于高速緩沖數(shù)據(jù)和索引。?
MyISAM的索引和數(shù)據(jù)是分開的,并且索引是有壓縮的,內(nèi)存使用率就對應(yīng)提高了不少。能加載更多索引,而Innodb是索引和數(shù)據(jù)是緊密捆綁的,沒有使用壓縮從而會造成Innodb比MyISAM體積龐大不小
8.3、事務(wù)處理?
MyISAM類型的表強調(diào)的是性能,其執(zhí)行數(shù)度比InnoDB類型更快,但是不支持外鍵、不提供事務(wù)支持。?
InnoDB提供事務(wù)支持事務(wù),外部鍵(foreign key)等高級數(shù)據(jù)庫功能。
SELECT、UPDATE、INSERT、Delete操作?
如果執(zhí)行大量的SELECT,MyISAM是更好的選擇。?
如果你的數(shù)據(jù)執(zhí)行大量的INSERT或UPDATE,出于性能方面的考慮,應(yīng)該使用InnoDB表。?
DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除。而MyISAM則是重新建立表。在innodb上如果要清空保存有大量數(shù)據(jù)的表,最好使用truncate table這個命令。
AUTO_INCREMENT?
MyISAM:可以和其他字段一起建立聯(lián)合索引。引擎的自動增長列必須是索引,如果是組合索引,自動增長可以不是第一列,他可以根據(jù)前面幾列進行排序后遞增。?
InnoDB:InnoDB中必須包含只有該字段的索引。引擎的自動增長列必須是索引,如果是組合索引也必須是組合索引的第一列。
8.4、表的具體行數(shù)?
MyISAM:保存有表的總行數(shù),如果select count(*) from table;會直接取出該值。?
InnoDB:沒有保存表的總行數(shù),如果使用select count(*) from table;就會遍歷整個表,消耗相當(dāng)大,但是在加了where后,myisam和innodb處理的方式都一樣。
8.5、全文索引?
MyISAM:支持 FULLTEXT類型的全文索引。不支持中文。?
InnoDB:不支持FULLTEXT類型的全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好。
8.6、表鎖差異?
MyISAM:只支持表級鎖,只支持表級鎖,用戶在操作myisam表時,select,update,delete,insert語句都會給表自動加鎖。?
InnoDB:支持事務(wù)和行級鎖,是innodb的最大特色。行鎖大幅度提高了多用戶并發(fā)操作的新能。但是InnoDB的行鎖也不是絕對的,如果在執(zhí)行一個SQL語句時MySQL不能確定要掃描的范圍,InnoDB表同樣會鎖全表, 例如update table set num=1 where name like “%aaa%”
一般來說:?
MyISAM適合:?
(1)做很多count 的計算;?
(2)插入不頻繁,查詢非常頻繁;?
(3)沒有事務(wù)。?
InnoDB適合:?
(1)可靠性要求比較高,或者要求事務(wù);?
(2)表更新和查詢都相當(dāng)?shù)念l繁,并且表鎖定的機會比較大的情況。
兩種類型最主要的差別就是Innodb 支持事務(wù)處理與外鍵和行級鎖。而MyISAM不支持.所以MyISAM往往就容易被人認(rèn)為只適合在小項目中使用。
作為使用MySQL的用戶角度出發(fā),Innodb和MyISAM都是比較喜歡的,如果數(shù)據(jù)庫平臺要達到需求:99.9%的穩(wěn)定性,方便的擴展性和高可用性來說的話,MyISAM絕對是首選。
原因如下:
1、平臺上承載的大部分項目是讀多寫少的項目,而MyISAM的讀性能是比Innodb強不少的。
2、MyISAM的索引和數(shù)據(jù)是分開的,并且索引是有壓縮的,內(nèi)存使用率就對應(yīng)提高了不少。能加載更多索引,而Innodb是索引和數(shù)據(jù)是緊密捆綁的,沒有使用壓縮從而會造成Innodb比MyISAM體積龐大不小。
3、經(jīng)常隔1,2個月就會發(fā)生應(yīng)用開發(fā)人員不小心update一個表where寫的范圍不對,導(dǎo)致這個表沒法正常用了,這個時候MyISAM的優(yōu)越性就體現(xiàn)出來了,隨便從當(dāng)天拷貝的壓縮包取出對應(yīng)表的文件,隨便放到一個數(shù)據(jù)庫目錄下,然后dump成sql再導(dǎo)回到主庫,并把對應(yīng)的binlog補上。如果是Innodb,恐怕不可能有這么快速度,別和我說讓Innodb定期用導(dǎo)出xxx.sql機制備份,因為最小的一個數(shù)據(jù)庫實例的數(shù)據(jù)量基本都是幾十G大小。
4、從接觸的應(yīng)用邏輯來說,select count(*) 和order by 是最頻繁的,大概能占了整個sql總語句的60%以上的操作,而這種操作Innodb其實也是會鎖表的,很多人以為Innodb是行級鎖,那個只是where對它主鍵是有效,非主鍵的都會鎖全表的。
5、還有就是經(jīng)常有很多應(yīng)用部門需要我給他們定期某些表的數(shù)據(jù),MyISAM的話很方便,只要發(fā)給他們對應(yīng)那表的frm.MYD,MYI的文件,讓他們自己在對應(yīng)版本的數(shù)據(jù)庫啟動就行,而Innodb就需要導(dǎo)出xxx.sql了,因為光給別人文件,受字典數(shù)據(jù)文件的影響,對方是無法使用的。
6、如果和MyISAM比insert寫操作的話,Innodb還達不到MyISAM的寫性能,如果是針對基于索引的update操作,雖然MyISAM可能會遜色Innodb,但是那么高并發(fā)的寫,從庫能否追的上也是一個問題,還不如通過多實例分庫分表架構(gòu)來解決。
7、如果是用MyISAM的話,merge引擎可以大大加快應(yīng)用部門的開發(fā)速度,他們只要對這個merge表做一些select count(*)操作,非常適合大項目總量約幾億的rows某一類型(如日志,調(diào)查統(tǒng)計)的業(yè)務(wù)表。
當(dāng)然Innodb也不是絕對不用,用事務(wù)的項目就用Innodb的。另外,可能有人會說你MyISAM無法抗太多寫操作,但是可以通過架構(gòu)來彌補。
總結(jié)
以上是生活随笔為你收集整理的interview-db的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GOM引擎ItemShow代码在NPC对
- 下一篇: 主流游戏引擎