- 前言:
在遨遊了一番 Java Web 的世界以後,發現了本身的一些缺失,因此就着一篇深度好文:知名互聯網公司校招 Java 開發崗面試知識點解析 ,來好好的對 Java 知識點進行復習和學習一番,大部份內容參照自這一篇文章,有一些本身補充的,也算是從新學習一下 Java 吧。html
前序文章連接:java
前排引用說明及好文推薦:面試/筆試第三彈 —— 數據庫面試問題集錦、數據庫常見面試題(開發者篇)segmentfault
存儲過程就像是編程語言中的函數同樣,封裝了咱們的代碼(PLSQL,T-SQL)緩存
例如:安全
-------------建立名爲GetUserAccount的存儲過程---------------- create Procedure GetUserAccount as select * from UserAccount go -------------執行上面的存儲過程---------------- exec GetUserAccount
存儲過程的優勢:
存儲過程的缺點:
- 思考這樣的一個例子:
咱們如今須要創建一個描述學校教務的數據庫,該數據庫涉及的對象包括學生的學號(Sno)、所在系(Sdept)、系主任姓名(Mname)、課程號(Cno)和成績(Grade),假設咱們使用單一的關係模式 Student 來表示,那麼根據現實世界已知的信息,會描述成如下這個樣子:
可是,這個關係模式存在如下問題:
(1) 數據冗餘
好比,每個系的系主任姓名重複出現,重複次數與該系全部學生的全部課程成績出現次數相同,這將浪費大量的存儲空間。
(2)更新異常(update anomalies)
因爲數據冗餘,當更新數據庫中的數據時,系統要付出很大的代價來維護數據庫的完整性,不然會面臨數據不一致的危險。好比,某系更換系主任後,必須修改與該系學生有關的每個元組。
(3)插入異常(insertion anomalies)
若是一個系剛成立,尚無學生,則沒法把這個系及其系主任的信息存入數據庫。
(4)刪除異常(deletion anomalies)
若是某個系的學生所有畢業了,則在刪除該系學生信息的同時,這個系及其系主任的信息也丟失了。
- 第一範式: 列不可分
1NF(第一範式)是對屬性具備原子性的要求,不可再分,例如:
若是認爲最後一列還能夠再分紅出生年,出生月,出生日,則它就不知足第一範式的要求。
- 第二範式: 消除非主屬性對碼的部分函數依賴
2NF(第二範式)是對記錄有惟一性的要求,即實體的惟一性,不存在部分依賴,每一列與主鍵都相關,例如:
該代表顯說明了兩個事物:學生信息和課程信息;正常的依賴應該是:學分依賴課程號,姓名依賴學號,但這裏存在非主鍵字段對碼的部分依賴,即與主鍵不相關,不知足第二範式的要求。
可能存在的問題:
正確的作法:
- 第三範式: 消除非主屬性對碼的傳遞函數依賴
3NF(第三範式)對字段有冗餘性的要求,任何字段不能由其餘字段派生出來,它要求字段沒有冗餘,即不存在依賴傳遞,例如:
很明顯,學院電話是一個冗餘字段,由於存在依賴傳遞:(學號)→(學生)→(學院)→(學院電話)
可能會存在的問題:
正確的作法:
- 什麼是索引?
索引是對數據庫表中一個或多個列的值進行排序的數據結構,以協助快速查詢、更新數據庫表中數據。
你也能夠這樣理解:索引就是加快檢索表中數據的方法。數據庫的索引相似於書籍的索引。在書籍中,索引容許用戶沒必要翻閱完整個書就能迅速地找到所須要的信息。在數據庫中,索引也容許數據庫程序迅速地找到表中的數據,而沒必要掃描整個數據庫。
- 底層數據結構是什麼,爲何使用這種數據結構?
(1)底層數據結構是B+樹:
在數據結構中,咱們最爲常見的搜索結構就是二叉搜索樹和AVL樹(高度平衡的二叉搜索樹,爲了提升二叉搜索樹的效率,減小樹的平均搜索長度)了。然而,不管二叉搜索樹仍是AVL樹,當數據量比較大時,都會因爲樹的深度過大而形成I/O讀寫過於頻繁,進而致使查詢效率低下,所以對於索引而言,多叉樹結構成爲不二選擇。特別地,B-Tree的各類操做能使B樹保持較低的高度,從而保證高效的查找效率。
(2)使用B+樹的緣由:
查找速度快、效率高,在查找的過程當中,每次都能拋棄掉一部分節點,減小遍歷個數。(此時,你應該在白紙上畫出什麼是B+樹)
- 索引的分類?
- 索引的優缺點?
(1)優勢:
(2)缺點:
- 什麼樣的字段適合建立索引?
- 建立索引時須要注意什麼?
非空字段:應該指定列爲NOT NULL,除非你想存儲NULL。在mysql中,含有空值的列很難進行查詢優化,由於它們使得索引、索引的統計信息以及比較運算更加複雜。你應該用0、一個特殊的值或者一個空串代替空值;
取值離散大的字段:(變量各個取值之間的差別程度)的列放到聯合索引的前面,能夠經過count()函數查看字段的差別值,返回值越大說明字段的惟一值越多字段的離散程度高;
索引字段越小越好:數據庫的數據存儲以頁爲單位一頁存儲的數據越多一次IO操做獲取的數據越大效率越高。
事務簡單來講:一個 Session 中所進行全部的操做,要麼同時成功,要麼同時失敗;做爲單個邏輯工做單元執行的一系列操做,知足四大特性:
- 實例說明:
/* * 咱們來模擬A向B帳號轉帳的場景 * A和B帳戶都有1000塊,如今我讓A帳戶向B帳號轉500塊錢 * **/ //JDBC默認的狀況下是關閉事務的,下面咱們看看關閉事務去操做轉帳操做有什麼問題 //A帳戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); //B帳戶多了500塊 String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate();
從上面看,咱們的確能夠發現A向B轉帳,成功了。但是若是A向B轉帳的過程當中出現了問題呢?下面模擬一下
// A帳戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); // 這裏模擬出現問題 int a = 3 / 0; String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate();
顯然,上面代碼是會拋出異常的,咱們再來查詢一下數據。A帳戶少了500塊錢,B帳戶的錢沒有增長。這明顯是不合理的。
咱們能夠經過事務來解決上面出現的問題:
// 開啓事務,對數據的操做就不會當即生效。 connection.setAutoCommit(false); // A帳戶減去500塊 String sql = "UPDATE a SET money=money-500 "; preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); // 在轉帳過程當中出現問題 int a = 3 / 0; // B帳戶多500塊 String sql2 = "UPDATE b SET money=money+500"; preparedStatement = connection.prepareStatement(sql2); preparedStatement.executeUpdate(); // 若是程序能執行到這裏,沒有拋出異常,咱們就提交數據 connection.commit(); // 關閉事務【自動提交】 connection.setAutoCommit(true); } catch(SQLException e) { try { // 若是出現了異常,就會進到這裏來,咱們就把事務回滾【將數據變成原來那樣】 connection.rollback(); // 關閉事務【自動提交】 connection.setAutoCommit(true); } catch (SQLException e1) { e1.printStackTrace(); } }
上面的程序也同樣拋出了異常,A帳戶錢沒有減小,B帳戶的錢也沒有增長。
隔離級別決定了一個session中的事務可能對另外一個session中的事務的影響。ANSI標準定義了4個隔離級別,MySQL的InnoDB都支持,分別是:
讀未提交(READ UNCOMMITTED):最低級別的隔離,一般又稱爲dirty read,它容許一個事務讀取另外一個事務還沒 commit 的數據,這樣可能會提升性能,可是會致使髒讀問題;
讀已提交(READ COMMITTED):在一個事務中只容許對其它事務已經 commit 的記錄可見,該隔離級別不能避免不可重複讀問題;
可重複讀(REPEATABLE READ):在一個事務開始後,其餘事務對數據庫的修改在本事務中不可見,直到本事務 commit 或 rollback。可是,其餘事務的 insert/delete 操做對該事務是可見的,也就是說,該隔離級別並不能避免幻讀問題。在一個事務中重複 select 的結果同樣,除非本事務中 update 數據庫。
序列化(SERIALIZABLE):最高級別的隔離,只容許事務串行執行。
MySQL默認的隔離級別是可重複讀(REPEATABLE READ)
- MySql 的事務支持
MySQL的事務支持不是綁定在MySQL服務器自己,而是與存儲引擎相關:
視圖是一種虛擬的表,具備和物理表相同的功能。能夠對視圖進行增,改,查,操做,試圖一般是有一個表或者多個表的行或列的子集。對視圖的修改不影響基本表。它使得咱們獲取數據更容易,相比多表查詢。
以下兩種場景通常會使用到視圖:
注意:這個視圖是在數據庫中建立的 而不是用代碼建立的。
drop 直接刪除表;truncate 刪除表中數據,再插入時自增加id又從1開始 ;delete 刪除表中數據,能夠加where字句。
- drop table:
- truncate table:
- delete from:
- 使用簡要說明:
觸發器是與表相關的數據庫對象,在知足定義條件時觸發,並執行觸發器中定義的語句集合。觸發器的這種特性能夠協助應用在數據庫端確保數據庫的完整性。
數據庫管理系統(DBMS)中的併發控制的任務是確保在多個事務同時存取數據庫中同一數據時不破壞事務的隔離性和統一性以及數據庫的統一性。
樂觀併發控制(樂觀鎖)和悲觀併發控制(悲觀鎖)是併發控制主要採用的技術手段。
- 悲觀鎖:假定會發生併發衝突,屏蔽一切可能違反數據完整性的操做
悲觀鎖是一種利用數據庫內部機制提供的鎖的方式,也就是對更新的數據加鎖,這樣在併發期間一旦有一個事務持有了數據庫記錄的鎖,其餘的線程將不能再對數據進行更新了,這就是悲觀鎖的實現方式。
MySQL InnoDB中使用悲觀鎖:
要使用悲觀鎖,咱們必須關閉mysql數據庫的自動提交屬性,由於MySQL默認使用autocommit模式,也就是說,當你執行一個更新操做後,MySQL會馬上將結果進行提交。 set autocommit=0;
//0.開始事務
begin;/begin work;/start transaction; (三者選一就能夠) //1.查詢出商品信息 select status from t_goods where id=1 for update; //2.根據商品信息生成訂單 insert into t_orders (id,goods_id) values (null,1); //3.修改商品status爲2 update t_goods set status=2; //4.提交事務 commit;/commit work;
上面的查詢語句中,咱們使用了 select…for update
的方式,這樣就經過開啓排他鎖的方式實現了悲觀鎖。此時在t_goods表中,id爲1的 那條數據就被咱們鎖定了,其它的事務必須等本次事務提交以後才能執行。這樣咱們能夠保證當前的數據不會被其它事務修改。
上面咱們提到,使用 select…for update
會把數據給鎖住,不過咱們須要注意一些鎖的級別,MySQL InnoDB默認行級鎖。行級鎖都是基於索引的,若是一條SQL語句用不到索引是不會使用行級鎖的,會使用表級鎖把整張表鎖住,這點須要注意。
優勢與不足:
悲觀併發控制其實是「先取鎖再訪問」的保守策略,爲數據處理的安全提供了保證。可是在效率方面,處理加鎖的機制會讓數據庫產生額外的開銷,還有增長產生死鎖的機會;另外,在只讀型事務處理中因爲不會產生衝突,也不必使用鎖,這樣作只能增長系統負載;還有會下降了並行性,一個事務若是鎖定了某行數據,其餘事務就必須等待該事務處理完才能夠處理那行數
- 樂觀鎖:假設不會發生併發衝突,只在提交操做時檢查是否違反數據完整性。
樂觀鎖是一種不會阻塞其餘線程併發的控制,它不會使用數據庫的鎖進行實現,它的設計裏面因爲不阻塞其餘線程,因此並不會引發線程頻繁掛起和恢復,這樣便可以提升併發能力,因此也有人把它稱爲非阻塞鎖。通常的實現樂觀鎖的方式就是記錄數據版本。
數據版本,爲數據增長的一個版本標識。當讀取數據時,將版本標識的值一同讀出,數據每更新一次,同時對版本標識進行更新。當咱們提交更新的時候,判斷數據庫表對應記錄的當前版本信息與第一次取出來的版本標識進行比對,若是數據庫表當前版本號與第一次取出來的版本標識值相等,則予以更新,不然認爲是過時數據。
實現數據版本有兩種方式,第一種是使用版本號,第二種是使用時間戳。
使用版本號實現樂觀鎖:
使用版本號時,能夠在數據初始化時指定一個版本號,每次對數據的更新操做都對版本號執行+1操做。並判斷當前版本號是否是該數據的最新的版本號。
1.查詢出商品信息
select (status,status,version) from t_goods where id=#{id} 2.根據商品信息生成訂單 3.修改商品status爲2 update t_goods set status=2,version=version+1 where id=#{id} and version=#{version};
優勢與不足:
樂觀併發控制相信事務之間的數據競爭(data race)的機率是比較小的,所以儘量直接作下去,直到提交的時候纔去鎖定,因此不會產生任何鎖和死鎖。但若是直接簡單這麼作,仍是有可能會遇到不可預期的結果,例如兩個事務都讀取了數據庫的某一行,通過修改之後寫回數據庫,這時就遇到了問題。
參考文章:深刻理解樂觀鎖與悲觀鎖
超鍵:在關係中能惟一標識元組的屬性集稱爲關係模式的超鍵。一個屬性能夠爲做爲一個超鍵,多個屬性組合在一塊兒也能夠做爲一個超鍵。超鍵包含候選鍵和主鍵。
候選鍵(候選碼):是最小超鍵,即沒有冗餘元素的超鍵。
主鍵(主碼):數據庫表中對儲存數據對象予以惟一和完整標識的數據列或屬性的組合。一個數據列只能有一個主鍵,且主鍵的取值不能缺失,即不能爲空值(Null)。
外鍵:在一個表中存在的另外一個表的主鍵稱此表的外鍵。
候選碼和主碼:
例子:郵寄地址(城市名,街道名,郵政編碼,單位名,收件人)
在MySQL 5.5以前,MyISAM是mysql的默認數據庫引擎,其由早期的ISAM(Indexed Sequential Access Method:有索引的順序訪問方法)所改良。雖然MyISAM性能極佳,但卻有一個顯著的缺點: 不支持事務處理。不過,MySQL也導入了另外一種數據庫引擎InnoDB,以強化參考完整性與併發違規處理機制,後來就逐漸取代MyISAM。
InnoDB是MySQL的數據庫引擎之一,其由Innobase oy公司所開發,2006年五月由甲骨文公司併購。與傳統的ISAM、MyISAM相比,InnoDB的最大特點就是支持ACID兼容的事務功能,相似於PostgreSQL。目前InnoDB採用雙軌制受權,一是GPL受權,另外一是專有軟件受權。具體地,MyISAM與InnoDB做爲MySQL的兩大存儲引擎的差別主要包括:
存儲結構:每一個MyISAM在磁盤上存儲成三個文件:第一個文件的名字以表的名字開始,擴展名指出文件類型。.frm文件存儲表定義,數據文件的擴展名爲.MYD (MYData),索引文件的擴展名是.MYI (MYIndex)。InnoDB全部的表都保存在同一個數據文件中(也多是多個文件,或者是獨立的表空間文件),InnoDB表的大小隻受限於操做系統文件的大小,通常爲2GB。
存儲空間:MyISAM可被壓縮,佔據的存儲空間較小,支持靜態表、動態表、壓縮表三種不一樣的存儲格式。InnoDB須要更多的內存和存儲,它會在主內存中創建其專用的緩衝池用於高速緩衝數據和索引。
可移植性、備份及恢復:MyISAM的數據是以文件的形式存儲,因此在跨平臺的數據轉移中會很方便,同時在備份和恢復時也可單獨針對某個表進行操做。InnoDB免費的方案能夠是拷貝數據文件、備份 binlog,或者用 mysqldump,在數據量達到幾十G的時候就相對痛苦了。
事務支持:MyISAM強調的是性能,每次查詢具備原子性,其執行數度比InnoDB類型更快,可是不提供事務支持。InnoDB提供事務、外鍵等高級數據庫功能,具備事務提交、回滾和崩潰修復能力。
AUTO_INCREMENT:在MyISAM中,能夠和其餘字段一塊兒創建聯合索引。引擎的自動增加列必須是索引,若是是組合索引,自動增加能夠不是第一列,它能夠根據前面幾列進行排序後遞增。InnoDB中必須包含只有該字段的索引,而且引擎的自動增加列必須是索引,若是是組合索引也必須是組合索引的第一列。
表鎖差別:MyISAM只支持表級鎖,用戶在操做MyISAM表時,select、update、delete和insert語句都會給表自動加鎖,若是加鎖之後的表知足insert併發的狀況下,能夠在表的尾部插入新的數據。InnoDB支持事務和行級鎖。行鎖大幅度提升了多用戶併發操做的新能,可是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的。
全文索引:MyISAM支持 FULLTEXT類型的全文索引;InnoDB不支持FULLTEXT類型的全文索引,可是innodb可使用sphinx插件支持全文索引,而且效果更好。
表主鍵:MyISAM容許沒有任何索引和主鍵的表存在,索引都是保存行的地址。對於InnoDB,若是沒有設定主鍵或者非空惟一索引,就會自動生成一個6字節的主鍵(用戶不可見),數據是主索引的一部分,附加索引保存的是主索引的值。
表的具體行數:MyISAM保存表的總行數,select count() from table;會直接取出出該值;而InnoDB沒有保存表的總行數,若是使用select count() from table;就會遍歷整個表,消耗至關大,可是在加了wehre條件後,myisam和innodb處理的方式都同樣。
CURD操做:在MyISAM中,若是執行大量的SELECT,MyISAM是更好的選擇。對於InnoDB,若是你的數據執行大量的INSERT或UPDATE,出於性能方面的考慮,應該使用InnoDB表。DELETE從性能上InnoDB更優,但DELETE FROM table時,InnoDB不會從新創建表,而是一行一行的刪除,在innodb上若是要清空保存有大量數據的表,最好使用truncate table這個命令。
外鍵:MyISAM不支持外鍵,而InnoDB支持外鍵。
經過上述的分析,基本上能夠考慮使用InnoDB來替代MyISAM引擎了,緣由是InnoDB自身不少良好的特色,好比事務支持、存儲過程、視圖、行級鎖、外鍵等等。尤爲在併發不少的狀況下,相信InnoDB的表現確定要比MyISAM強不少。另外,必須須要注意的是,任何一種表都不是萬能的,合適的纔是最好的,才能最大的發揮MySQL的性能優點。若是是不復雜的、非關鍵的Web應用,仍是能夠繼續考慮MyISAM的,這個具體狀況具體考慮。
答案:都是B+樹!
MyIASM引擎,B+樹的數據結構中存儲的內容其實是實際數據的地址值。也就是說它的索引和實際數據是分開的,只不過使用索引指向了實際數據。這種索引的模式被稱爲非彙集索引。
Innodb引擎的索引的數據結構也是B+樹,只不過數據結構中存儲的都是實際的數據,這種索引有被稱爲彙集索引。
char是一種固定長度的類型,varchar是一種可變長度的類型,例如:
定義一個char[10]和varchar[10],若是存進去的是 'test',那麼char所佔的長度依然爲10,除了字符 'test' 外,後面跟六個空格,varchar就立馬把長度變爲4了,取數據的時候,char類型的要用trim()去掉多餘的空格,而varchar是不須要的
char的存取速度仍是要比varchar要快得多,由於其長度固定,方便程序的存儲於查找
char也爲此付出的是空間的代價,由於其長度固定,因此不免會有多餘的空格佔位符佔據空間,可謂是以空間換取時間效率。
varchar是以空間效率爲首位。
char的存儲方式是:對英文字符(ASCII)佔用1個字節,對一個漢字佔用兩個字節。
varchar的存儲方式是:對每一個英文字符佔用2個字節,漢字也佔用2個字節。
二者的存儲數據都非unicode的字符數據。
主鍵:指字段 惟1、不爲空值 的列;
主鍵索引:指的就是主鍵,主鍵是索引的一種,是惟一索引的特殊類型。建立主鍵的時候,數據庫默認會爲主鍵建立一個惟一索引;
自增主鍵:字段類型爲數字、自增、而且是主鍵;
惟一索引:索引列的值必須惟一,但容許有空值。主鍵是惟一索引,這樣說沒錯;但反過來講,惟一索引也是主鍵就錯誤了,由於惟一索引容許空值,主鍵不容許有空值,因此不能說惟一索引也是主鍵。
主鍵是一種特殊的惟一性索引,其能夠是彙集索引,也能夠是非彙集索引。在SQLServer中,主鍵的建立必須依賴於索引,默認建立的是彙集索引,但也能夠顯式指定爲非彙集索引。InnoDB做爲MySQL存儲引擎時,默認按照主鍵進行彙集,若是沒有定義主鍵,InnoDB會試着使用惟一的非空索引來代替。若是沒有這種索引,InnoDB就會定義隱藏的主鍵而後在上面進行彙集。因此,對於彙集索引來講,你建立主鍵的時候,自動就建立了主鍵的彙集索引。
實踐中,MySQL的優化主要涉及SQL語句及索引的優化、數據表結構的優化、系統配置的優化和硬件的優化四個方面,以下圖所示:
SQL語句的優化主要包括三個問題,即如何發現有問題的SQL、如何分析SQL的執行計劃以及如何優化SQL,下面將逐一解釋。
① 怎麼發現有問題的SQL?(經過MySQL慢查詢日誌對有效率問題的SQL進行監控)
MySQL的慢查詢日誌是MySQL提供的一種日誌記錄,它用來記錄在MySQL中響應時間超過閥值的語句,具體指運行時間超過long_query_time值的SQL,則會被記錄到慢查詢日誌中。long_query_time的默認值爲10,意思是運行10s以上的語句。慢查詢日誌的相關參數以下所示:
經過MySQL的慢查詢日誌,咱們能夠查詢出執行的次數多佔用的時間長的SQL、能夠經過pt_query_disgest(一種mysql慢日誌分析工具)分析Rows examine(MySQL執行器須要檢查的行數)項去找出IO大的SQL以及發現未命中索引的SQL,對於這些SQL,都是咱們優化的對象。
② 經過explain查詢和分析SQL的執行計劃:
使用 EXPLAIN 關鍵字能夠知道MySQL是如何處理你的SQL語句的,以便分析查詢語句或是表結構的性能瓶頸。經過explain命令能夠獲得表的讀取順序、數據讀取操做的操做類型、哪些索引可使用、哪些索引被實際使用、表之間的引用以及每張表有多少行被優化器查詢等問題。當擴展列extra出現Using filesort和Using temporay,則每每表示SQL須要優化了。
③ SQL語句的優化:
⒈優化insert語句:一次插入多值;
⒉應儘可能避免在 where 子句中使用!=或<>操做符,不然將引擎放棄使用索引而進行全表掃描;
⒊應儘可能避免在 where 子句中對字段進行null值判斷,不然將致使引擎放棄使用索引而進行全表掃描;
⒋優化嵌套查詢:子查詢能夠被更有效率的鏈接(Join)替代;
⒌不少時候用 exists 代替 in 是一個好的選擇。
⒍選擇最有效率的表名順序:數據庫的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表將被最早處理
在FROM子句中包含多個表的狀況下:
若是有3個以上的錶鏈接查詢:
⒎用IN代替OR:
select * from emp where sal = 1500 or sal = 3000 or sal = 800; select * from emp where sal in (1500,3000,800);
⒏SELECT子句中避免使用*號:
咱們最開始接觸 SQL 的時候,「*
」 號是能夠獲取表中所有的字段數據的,可是它要經過查詢數據字典完成,這意味着將消耗更多的時間,並且使用 「*
」 號寫出來的 SQL 語句也不夠直觀。
建議在常常做查詢選擇的字段、常常做錶鏈接的字段以及常常出如今 order by、group by、distinct 後面的字段中創建索引。但必須注意如下幾種可能會引發索引失效的情形:
以 「%(表示任意0個或多個字符)」 開頭的 LIKE 語句,模糊匹配;
OR語句先後沒有同時使用索引;
數據類型出現隱式轉化(如varchar不加單引號的話可能會自動轉換爲int型);
對於多列索引,必須知足最左匹配原則(eg,多列索引col一、col2和col3,則 索引生效的情形包括col1或col1,col2或col1,col2,col3)。
① 選擇合適數據類型:
② 表的範式的優化:
通常狀況下,表的設計應該遵循三大範式。
③ 表的垂直拆分:
把含有多個列的表拆分紅多個表,解決表寬度問題,具體包括如下幾種拆分手段:
這樣作的好處是很是明顯的,具體包括:拆分後業務清晰,拆分規則明確、系統之間整合或擴展容易、數據維護簡單
④ 表的水平拆分:
表的水平拆分用於解決數據表中數據過大的問題,水平拆分每個表的結構都是徹底一致的。通常地,將數據平分到N張表中的經常使用方法包括如下兩種:
表的水平拆分會帶來一些問題和挑戰,包括跨分區表的數據查詢、統計及後臺報表的操做等問題,但也帶來了一些切實的好處:
操做系統配置的優化:增長TCP支持的隊列數
mysql配置文件優化:Innodb緩存池設置(innodb_buffer_pool_size,推薦總內存的75%)和緩存池的個數(innodb_buffer_pool_instances)
歡迎轉載,轉載請註明出處!轉載自@我沒有三顆心臟