1. 程式人生 > >百度面試經驗和流程

百度面試經驗和流程

筆者小菜雞一枚,今天有幸去百度面試,感覺大公司就是不一樣,所以感覺有必要總結一下面試經驗,以及面試中遇到的一些問題,以便大家參考:

1.我面試地點是百度科技園,第一關就是不知道如何進門,尷尬,首先要聯絡你的面試邀請人,他會幫你去搞一個面試邀請簡訊發到你的手機上,你憑這個簡訊才能進入科技園,然後進入大廳,去前臺,點選簡訊中的連結 去列印一個二維碼,再告知的面試官,讓他下來接你。
2. 一般他會把你領到一個開放的會議室,或者叫休息區更合適,接著你把簡歷交給他,他一般會說簡單介紹自己一下吧,或者說說你的上一家的工作。接著你就巴啦巴拉的說就完了。這個時候面試官會邊聽你講,邊看你的簡歷。如果你講的東西他感興趣,他就會問你一些問題,以下是我被問到的一些問題:

1.說一下你對spring的理解(aop和ioc)

IoC(Inversion of Control)

(1). IoC(Inversion of Control)是指容器控制程式物件之間的關係,而不是傳統實現中,由程式程式碼直接操控。控制權由應用程式碼中轉到了外部容器,控制權的轉移是所謂反轉。 對於Spring而言,就是由Spring來控制物件的生命週期和物件之間的關係;IoC還有另外一個名字——“依賴注入(Dependency Injection)”。從名字上理解,所謂依賴注入,即元件之間的依賴關係由容器在執行期決定,即由容器動態地將某種依賴關係注入到元件之中。

(2). 在Spring的工作方式中,所有的類都會在spring容器中登記,告訴spring這是個什麼東西,你需要什麼東西,然後spring會在系統執行到適當的時候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的建立、銷燬都由 spring來控制,也就是說控制物件生存週期的不再是引用它的物件,而是spring。對於某個具體的物件而言,以前是它控制其他物件,現在是所有物件都被spring控制,所以這叫控制反轉。

(3). 在系統執行中,動態的向某個物件提供它所需要的其他物件。

(4). 依賴注入的思想是通過反射機制實現的,在例項化一個類時,它通過反射呼叫類中set方法將事先儲存在HashMap中的類屬性注入到類中。 總而言之,在傳統的物件建立方式中,通常由呼叫者來建立被呼叫者的例項,而在Spring中建立被呼叫者的工作由Spring來完成,然後注入呼叫者,即所謂的依賴注入or控制反轉。 注入方式有兩種:依賴注入和設定注入; IoC的優點:降低了元件之間的耦合,降低了業務物件之間替換的複雜性,使之能夠靈活的管理物件。

AOP(Aspect Oriented Programming)

(1). AOP面向方面程式設計基於IoC,是對OOP的有益補充;

(2). AOP利用一種稱為“橫切”的技術,剖解開封裝的物件內部,並將那些影響了 多個類的公共行為封裝到一個可重用模組,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模組所共同呼叫的 邏輯或責任封裝起來,比如日誌記錄,便於減少系統的重複程式碼,降低模組間的耦合度,並有利於未來的可操作性和可維護性。

(3). AOP代表的是一個橫向的關 系,將“物件”比作一個空心的圓柱體,其中封裝的是物件的屬性和行為;則面向方面程式設計的方法,就是將這個圓柱體以切面形式剖開,選擇性的提供業務邏輯。而 剖開的切面,也就是所謂的“方面”了。然後它又以巧奪天功的妙手將這些剖開的切面復原,不留痕跡,但完成了效果。

(4). 實現AOP的技術,主要分為兩大類:一是採用動態代理技術,利用擷取訊息的方式,對該訊息進行裝飾,以取代原有物件行為的執行;二是採用靜態織入的方式,引入特定的語法建立“方面”,從而使得編譯器可以在編譯期間織入有關“方面”的程式碼。

(5). Spring實現AOP:JDK動態代理和CGLIB代理 JDK動態代理:其代理物件必須是某個介面的實現,它是通過在執行期間建立一個介面的實現類來完成對目標物件的代理;其核心的兩個類是InvocationHandler和Proxy。 CGLIB代理:實現原理類似於JDK動態代理,只是它在執行期間生成的代理物件是針對目標類擴充套件的子類。CGLIB是高效的程式碼生成包,底層是依靠ASM(開源的java位元組碼編輯類庫)操作位元組碼實現的,效能比JDK強;需要引入包asm.jar和cglib.jar。 使用AspectJ注入式切面和@AspectJ註解驅動的切面實際上底層也是通過動態代理實現的。

(6). AOP使用場景:

Authentication 許可權檢查

Caching 快取

Context passing 內容傳遞

Error handling 錯誤處理

Lazy loading 延遲載入

Debugging  除錯

logging, tracing, profiling and monitoring 日誌記錄,跟蹤,優化,校準

Performance optimization 效能優化,效率檢查

Persistence  持久化

Resource pooling 資源池

Synchronization 同步

Transactions 事務管理

另外Filter的實現和struts2的攔截器的實現都是AOP思想的體現。

2.spring的幾種注入方式

在Spring容器中為一個bean配置依賴注入有三種方式:

· 使用屬性的setter方法注入 這是最常用的方式;
· 使用構造器注入;
· 使用Filed注入(用於註解方式).

使用屬性的setter方法注入

首先要配置被注入的bean,在該bean對應的類中,應該有要注入的物件屬性或者基本資料型別的屬性。例如:為UserBiz類注入UserDAO,同時為UserBiz注入基本資料型別String,那麼這時,就要為UserDAO物件和String型別設定setter方法.,用於進行依賴注入。

如何配置該bean呢?

<bean id="userBiz" class="com.text.biz.impl.UserBizImpl">

<property name="userDao">

<ref>userDao</ref>

</property>

</bean>

以上就是一個使用屬性的setter方法的方式進行依賴注入。

使用構造器注入

第一,在PersonBiz類中注入PersonDAO和一個String型別的資料;在該類中,不用為PersonDAO屬性和String資料型別的屬性設定setter方法,但是需要生成該類的構造方法;如下:

public class PersonBizImpl implements PersonBiz {

// 宣告"依賴物件"PersonDAO

PersonDAO personDao = null;

// 宣告"依賴的基本資料型別"

String str = null;

// 生成無參構造方法

public PersonBizImpl() {

super();

}

// 生成帶參構造方法

public PersonBizImpl(PersonDAO personDao, String str) {

super();

this.personDao = personDao;

this.str = str;

}

public void addPerson() {

this.personDao.addPerson();

System.out.println(str);

}

}

第二,在配置檔案中配置該類的bean,並配置構造器,在配置構造器中用到了節點,該節點有四個屬性:

· index是索引,指定注入的屬性,從0開始,如:0代表personDao,1代表str屬性;

· type是指該屬性所對應的型別,如Persondao對應的是com.aptech.dao.PersonDAO;

· ref 是指引用的依賴物件;

· value 當注入的不是依賴物件,而是基本資料型別時,就用value;

如下:

<!-- 利用構造器配置依賴注入 -->

<bean id="personDao" class="com.aptech.dao.impl.PersonDAOImpl"></bean>

<bean id="personBiz" class="com.aptech.biz.impl.PersonBizImpl">

<constructorarg index="0" type="com.aptech.dao.PersonDAO"ref="personDao"></constructor-arg>

<constructor-arg index="1" value="Spring學習"></constructor-arg>

</bean>

使用欄位(Filed)注入(用註解方式)

在Spring中,注入依賴物件可以採用手工裝配或自動裝配,在實際應用開發中建議使用手工裝配,因為自動裝配會產生許多未知情況,開發人員無法預見最終的裝配結果。

手工裝配依賴物件又分為兩種方式:

一種是在XML檔案中,通過在bean節點下配置;如上面講到的使用屬性的setter方法注入依賴物件和使用構造器方法注入依賴物件都是這種方式。

另一種就是在java程式碼中使用註解的方式進行裝配,在程式碼中加入@Resource或者@Autowired、

怎樣使用註解的方式來為某個bena注入依賴物件呢?

首先,我們需要在Spring容器的配置檔案applicationContext.Xml檔案中配置以下資訊,該信心是一個Spring配置檔案的模板:

<?xml version="1.0" encoding="UTF-8"?>

<beans

xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:p="http://www.springframework.org/schema/p"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd

">

</beans>

注意:只有配置了紅色部分的程式碼才可以引入註解的名稱空間,否則報錯。 以上的配置隱式的註冊了多個對註釋進行解析的處理器:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor等。

其次,在配置檔案中開啟context:annotation-config節點,告訴Spring容器可以用註解的方式注入依賴物件;其在配置檔案中的程式碼如下:

<beans>

……

<context:annotation-config></context:annotation-config>

……

</beans>

第三,在配置檔案中配置bean物件,如下:

<bean id="userDao" class="com.springtest.dao.impl.UserDAOImpl"></bean>

<bean id="userBiz" class="com.springtest.biz.impl.UserBizImpl"></bean>

第四,在需要依賴注入的BIZ類中,宣告一個依賴物件,不用生成該依賴物件的setter方法,並且為該物件添加註解:

public class UserBizImpl implements UserBiz {

@Resource(name="userDao")

private UserDAO userDao = null;

public void addUser() {

this.userDao.addUser();

}

}

其中,在Java程式碼中可以使用@Autowired或@Resource註解方式進行Spring的依賴注入。兩者的區別是:@Autowired預設按型別裝配,@Resource預設按名稱裝配,當找不到與名稱匹配的bean時,才會按型別裝配。

比如:我們用@Autowired為上面的程式碼UserDAO介面的例項物件進行註解,它會到Spring容器中去尋找與UserDAO物件相匹配的型別,如果找到該型別則將該型別注入到userdao欄位中;

如果用@Resource進行依賴注入,它先會根據指定的name屬性去Spring容器中尋找與該名稱匹配的型別,例如:@Resource(name=“userDao”),如果沒有找到該名稱,則會按照型別去尋找,找到之後,會對欄位userDao進行注入。

通常我們使用@Resource。

使用註解注入依賴物件不用再在程式碼中寫依賴物件的setter方法或者該類的構造方法,並且不用再配置檔案中配置大量的依賴物件,使程式碼更加簡潔,清晰,易於維護。

在Spring IOC程式設計的實際開發中推薦使用註解的方式進行依賴注入。

~~
依賴注入—自動裝配 Spring中提供了自動裝配依賴物件的機制,但是在實際應用中並不推薦使用自動裝配,因為自動裝配會產生未知情況,開發人員無法預見最終的裝配結果。 自動裝配是在配置檔案中實現的,如下: 只需要配置一個autowire屬性即可完成自動裝配,不用再配置檔案中寫,但是在類中還是要生成依賴物件的setter方法。 Autowire的屬性值有如下幾個: · byType 按型別裝配 可以根據屬性型別,在容器中尋找該型別匹配的bean,如有多個,則會丟擲異常,如果沒有找到,則屬性值為null; · byName 按名稱裝配 可以根據屬性的名稱在容器中查詢與該屬性名稱相同的bean,如果沒有找到,則屬性值為null; · constructor 與byType方式相似,不同之處在與它應用於構造器引數,如果在容器中沒有找到與構造器引數型別一致的bean,那麼將丟擲異常; · autodetect 通過bean類的自省機制(introspection)來決定是使用constructor還是byType的方式進行自動裝配。如果發現預設的構造器,那麼將使用byType的方式。

3.spring常用的註解

Spring常用註解
使用註解來構造IoC容器
用註解來向Spring容器註冊Bean。需要在applicationContext.xml中註冊<context:component-scan base-package=”pagkage1[,pagkage2,…,pagkageN]”/>。

如:在base-package指明一個包

1 <context:component-scan base-package=“cn.gacl.java”/>
表明cn.gacl.java包及其子包中,如果某個類的頭上帶有特定的註解【@Component/@Repository/@Service/@Controller】,就會將這個物件作為Bean註冊進Spring容器。也可以在<context:component-scan base-package=” ”/>中指定多個包,如:

1 <context:component-scan base-package="cn.gacl.dao.impl,cn.gacl.service.impl,cn.gacl.action"/>

多個包逗號隔開。

1、@Component
@Component
是所有受Spring 管理元件的通用形式,@Component註解可以放在類的頭上,@Component不推薦使用。

2、@Controller
@Controller對應表現層的Bean,也就是Action,例如:

1 @Controller
2 @Scope("prototype")
3 public class UserAction extends BaseAction<User>{
4 ……
5 }

使用@Controller註解標識UserAction之後,就表示要把UserAction交給Spring容器管理,在Spring容器中會存在一個名字為"userAction"的action,這個名字是根據UserAction類名來取的。注意:如果@Controller不指定其value【@Controller】,則預設的bean名字為這個類的類名首字母小寫,如果指定value【@Controller(value=“UserAction”)】或者【@Controller(“UserAction”)】,則使用value作為bean的名字。

這裡的UserAction還使用了@Scope註解,@Scope(“prototype”)表示將Action的範圍宣告為原型,可以利用容器的scope="prototype"來保證每一個請求有一個單獨的Action來處理,避免struts中Action的執行緒安全問題。spring 預設scope 是單例模式(scope=“singleton”),這樣只會建立一個Action物件,每次訪問都是同一Action物件,資料不安全,struts2 是要求每次次訪問都對應不同的Action,scope=“prototype” 可以保證當有請求的時候都建立一個Action物件

3、@ Service
@Service對應的是業務層Bean,例如:

1 @Service("userService")
2 public class UserServiceImpl implements UserService {
3 ………
4 }

@Service(“userService”)註解是告訴Spring,當Spring要建立UserServiceImpl的的例項時,bean的名字必須叫做"userService",這樣當Action需要使用UserServiceImpl的的例項時,就可以由Spring建立好的"userService",然後注入給Action:在Action只需要宣告一個名字叫“userService”的變數來接收由Spring注入的"userService"即可,具體程式碼如下:

1 // 注入userService
2 @Resource(name = "userService")
3 private UserService userService;

注意:在Action宣告的“userService”變數的型別必須是“UserServiceImpl”或者是其父類“UserService”,否則由於型別不一致而無法注入,由於Action中的宣告的“userService”變數使用了@Resource註解去標註,並且指明瞭其name = “userService”,這就等於告訴Spring,說我Action要例項化一個“userService”,你Spring快點幫我例項化好,然後給我,當Spring看到userService變數上的@Resource的註解時,根據其指明的name屬性可以知道,Action中需要用到一個UserServiceImpl的例項,此時Spring就會把自己建立好的名字叫做"userService"的UserServiceImpl的例項注入給Action中的“userService”變數,幫助Action完成userService的例項化,這樣在Action中就不用通過“UserService userService = new UserServiceImpl();”這種最原始的方式去例項化userService了。如果沒有Spring,那麼當Action需要使用UserServiceImpl時,必須通過“UserService userService = new UserServiceImpl();”主動去建立例項物件,但使用了Spring之後,Action要使用UserServiceImpl時,就不用主動去建立UserServiceImpl的例項了,建立UserServiceImpl例項已經交給Spring來做了,Spring把建立好的UserServiceImpl例項給Action,Action拿到就可以直接用了。Action由原來的主動建立UserServiceImpl例項後就可以馬上使用,變成了被動等待由Spring建立好UserServiceImpl例項之後再注入給Action,Action才能夠使用。這說明Action對“UserServiceImpl”類的“控制權”已經被“反轉”了,原來主動權在自己手上,自己要使用“UserServiceImpl”類的例項,自己主動去new一個出來馬上就可以使用了,但現在自己不能主動去new“UserServiceImpl”類的例項,new“UserServiceImpl”類的例項的權力已經被Spring拿走了,只有Spring才能夠new“UserServiceImpl”類的例項,而Action只能等Spring建立好“UserServiceImpl”類的例項後,再“懇求”Spring把建立好的“UserServiceImpl”類的例項給他,這樣他才能夠使用“UserServiceImpl”,這就是Spring核心思想“控制反轉”,也叫“依賴注入”,“依賴注入”也很好理解,Action需要使用UserServiceImpl幹活,那麼就是對UserServiceImpl產生了依賴,Spring把Acion需要依賴的UserServiceImpl注入(也就是“給”)給Action,這就是所謂的“依賴注入”。對Action而言,Action依賴什麼東西,就請求Spring注入給他,對Spring而言,Action需要什麼,Spring就主動注入給他。

4、@ Repository
@Repository對應資料訪問層Bean ,例如:

1 @Repository(value="userDao")
2 public class UserDaoImpl extends BaseDaoImpl<User> {
3 ………
4 }

@Repository(value=“userDao”)註解是告訴Spring,讓Spring建立一個名字叫“userDao”的UserDaoImpl例項。

當Service需要使用Spring建立的名字叫“userDao”的UserDaoImpl例項時,就可以使用@Resource(name = “userDao”)註解告訴Spring,Spring把建立好的userDao注入給Service即可。

1 // 注入userDao,從資料庫中根據使用者Id取出指定使用者時需要用到
2 @Resource(name = "userDao")
3 private BaseDao<User> userDao;

4.使用spring要引入哪些jar包

<dependencies>
  <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.2.4.RELEASE</version>
</dependency>
  <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.2.4.RELEASE</version>
</dependency>
  <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>4.2.4.RELEASE</version>
</dependency>
  <!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>4.2.4.RELEASE</version>
</dependency>
<!-- junit單元測試 -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.9</version>
		<scope>test</scope>
	</dependency>
  </dependencies>

5.spring如何解決迴圈注入問題

第一種,解決setter物件的依賴,就是說在A類需要設定B類,B類需要設定C類,C類需要設定A類,這時就出現一個死迴圈,

spring的解決方案是,初始化A類時把A類的初始化Bean放到快取中,然後set B類,再把B類的初始化Bean放到快取中,

然後set C類,初始化C類需要A類和B類的Bean,這時不需要初始化,只需要從快取中取出即可.

該種僅對single作用的Bean起作用,因為prototype作用的Bean,Spring不對其做快取

第二種,解決構造器中對其它類的依賴,建立A類需要構造器中初始化B類,建立B類需要構造器中初始化C類,建立C類需要構造器中又要初始化A類,因而形成一個死迴圈,Spring的解決方案是,把建立中的Bean放入到一個“當前建立Bean池”中,在初始化類的過程中,如果發現Bean類已存在,就丟擲一個“BeanCurrentInCreationException”的異常

6.mysql資料庫的常見優化手段有哪些

Mysql的優化,大體可以分為三部分:索引的優化,sql語句的優化,表的優化

1.索引的優化

只要列中含有NULL值,就最好不要在此例設定索引,複合索引如果有NULL值,此列在使用時也不會使用索引
儘量使用短索引,如果可以,應該制定一個字首長度
對於經常在where子句使用的列,最好設定索引,這樣會加快查詢速度
對於有多個列where或者order by子句的,應該建立複合索引
對於like語句,以%或者‘-’開頭的不會使用索引,以%結尾會使用索引
儘量不要在列上進行運算(函式操作和表示式操作)
儘量不要使用not in和<>操作

2.sql語句的優化

查詢時,能不要就不用,儘量寫全欄位名
大部分情況連線效率遠大於子查詢
多使用explain和profile分析查詢語句
檢視慢查詢日誌,找出執行時間長的sql語句優化
多表連線時,儘量小表驅動大表,即小表 join 大表
在千萬級分頁時使用limit
對於經常使用的查詢,可以開啟快取

3.表的優化

表的欄位儘可能用NOT NULL
欄位長度固定的表查詢會更快
把資料庫的大表按時間或一些標誌分成小表
將表分割槽

7.mysql和redis的區別

MySQL是關係型資料庫,是持久化儲存的,查詢檢索的話,會涉及到磁碟IO操作,為了提高效能,可以使用快取技術,而memcached就是記憶體資料庫,資料儲存在記憶體中(當然也可以進行持久化儲存),可以用作快取資料庫。使用者首先去memcached查詢資料,如果未查詢到(即快取未命中),才去MySQL中查詢資料,查詢到的資料會更新到快取資料庫中,提供給下次可能進行的查詢。提高了資料查詢方面的效能。

Redis和memcached都是快取資料庫,可以大大提升高資料量的web訪問速度。但是memcached只是提供了簡單的資料結構string,而Redis的value可以是string、list、set、hash、sorted set這些,功能更加強大。

web應用中一般採用MySQL+Redis的方式,web應用每次先訪問Redis,如果沒有找到資料,才去訪問MySQL。

Redis是記憶體資料庫,資料儲存在記憶體中,訪問速度快。MySQL是關係型資料庫,功能強大,儲存在磁碟中,資料訪問速度慢。像memcached,MongoDB,Redis等,都屬於No sql系列。

8.mysql如何建立索引,以及依據,如何判斷索引是否生效

在mysql中使用索引的原則有以下幾點:

1、 對於查詢頻率高的欄位建立索引;

2、 對排序、分組、聯合查詢頻率高的欄位建立索引;

3、 索引的數目不宜太多
原因:a、每建立一個索引都會佔用相應的物理控制元件;
   b、過多的索引會導致insert、update、delete語句的執行效率降低;

4、若在實際中,需要將多個列設定索引時,可以採用多列索引
如:某個表(假設表名為Student),存在多個欄位(StudentNo, StudentName, Sex, Address, Phone, BirthDate),其中需要對StudentNo,StudentName欄位進行查詢,對Sex欄位進行分組,對BirthDate欄位進行排序,此時可以建立多列索引
index index_name (StudentNo, StudentName, Sex, BirthDate); #index_name為索引名
在上面的語句中只建立了一個索引,但是對4個欄位都賦予了索引的功能。
建立多列索引,需要遵循BTree型別,
即第一列使用時,才啟用索引。
在上面的建立語句中,只有mysql語句在使用到StudentNo欄位時,索引才會被啟用。
如: select * from Student where StudentNo = 1000; #使用到了StudentNo欄位,索引被啟用。
可以使用explain檢測索引是否被啟用
如:explain select * from Student where StudentNo = 1000;

5、選擇唯一性索引
唯一性索引的值是唯一的,可以更快速的通過該索引來確定某條記錄。例如,學生表中學號是具有唯一性的欄位。為該欄位建立唯一性索引可以很快的確定某個學生的資訊。如果使用姓名的話,可能存在同名現象,從而降低查詢速度。

6、儘量使用資料量少的索引
如果索引的值很長,那麼查詢的速度會受到影響。例如,對一個CHAR(100)型別的欄位進行全文檢索需要的時間肯定要比對CHAR(10)型別的欄位需要的時間要多。

7、儘量使用字首來索引
如果索引欄位的值很長,最好使用值的字首來索引。例如,TEXT和BLOG型別的欄位,進行全文檢索會很浪費時間。如果只檢索欄位的前面的若干個字元,這樣可以提高檢索速度。

8、刪除不再使用或者很少使用的索引.
表中的資料被大量更新,或者資料的使用方式被改變後,原有的一些索引可能不再需要。資料庫管理員應當定期找出這些索引,將它們刪除,從而減少索引對更新操作的影響
使用方法,在select語句前加上explain就可以了:

EXPLAIN SELECT surname,first_name form a,b WHERE a.id=b.id

EXPLAIN列的解釋:

table:顯示這一行的資料是關於哪張表的。

type:這是重要的列,顯示連線使用了何種型別。從最好到最差的連線型別為const、eq_reg、ref、range、index和ALL。

possible_keys:顯示可能應用在這張表中的索引。如果為空,沒有可能的索引。可以為相關的域從WHERE語句中選擇一個合適的語句。

key: 實際使用的索引。如果為NULL,則沒有使用索引。很少的情況下,MySQL會選擇優化不足的索引。這種情況下,可以在SELECT語句中使用USE INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MySQL忽略索引。

key_len:使用的索引的長度。在不損失精確性的情況下,長度越短越好。

ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數。

rows:MySQL認為必須檢查的用來返回請求資料的行數。

Extra:關於MySQL如何解析查詢的額外資訊。

extra列返回的描述的意義:

Distinct: 一旦MySQL找到了與行相聯合匹配的行,就不再搜尋了。

Not exists: MySQL優化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標準的行,就不再搜尋了。

Range checked for each Record(index map:#): 沒有找到理想的索引,因此對於從前面表中來的每一個行組合,MySQL檢查使用哪個索引,並用它來從表中返回行。這是使用索引的最慢的連線之一。

Using filesort: 看到這個的時候,查詢就需要優化了。MySQL需要進行額外的步驟來發現如何對返回的行排序。它根據連線型別以及儲存排序鍵值和匹配條件的全部行的行指標來排序全部行。

Using index: 列資料是從僅僅使用了索引中的資訊而沒有讀取實際的行動的表返回的,這發生在對錶的全部的請求列都是同一個索引的部分的時候。

Using temporary: 看到這個的時候,查詢需要優化了。這裡,MySQL需要建立一個臨時表來儲存結果,這通常發生在對不同的列集進行ORDER BY上,而不是GROUP BY上。

Where used: 使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給使用者。如果不想返回表中的全部行,並且連線型別ALL或index,這就會發生,或者是查詢有問題不同連線型別的解釋(按照效率高低的順序排序)。

system: 表只有一行:system表。這是const連線型別的特殊情況。

const: 表中的一個記錄的最大值能夠匹配這個查詢(索引可以是主鍵或惟一索引)。因為只有一行,這個值實際就是常數,因為MySQL先讀這個值然後把它當做常數來對待。

eq_ref: 在連線中,MySQL在查詢時,從前面的表中,對每一個記錄的聯合都從表中讀取一個記錄,它在查詢使用了索引為主鍵或惟一鍵的全部時使用。

ref: 這個連線型別只有在查詢使用了不是惟一或主鍵的鍵或者是這些型別的部分(比如,利用最左邊字首)時發生。對於之前的表的每一個行聯合,全部記錄都將從表中讀出。這個型別嚴重依賴於根據索引匹配的記錄多少—越少越好。

range: 這個連線型別使用索引返回一個範圍中的行,比如使用>或<查詢東西時發生的情況。

index: 這個連線型別對前面的表中的每一個記錄聯合進行完全掃描(比ALL更好,因為索引一般小於表資料)。

ALL: 這個連線型別對於前面的每一個記錄聯合進行完全掃描,這一般比較糟糕,應該儘量避免。

9.mysql的資料庫引擎有哪些,他們之間的差別是啥

資料庫引擎介紹

MySQL資料庫引擎取決於MySQL在安裝的時候是如何被編譯的。要新增一個新的引擎,就必須重新編譯MYSQL。在預設情況下,MYSQL支援三個引擎:ISAM、MYISAM和HEAP。另外兩種型別INNODB和BERKLEY(BDB),也常常可以使用。如果技術高超,還可以使用MySQL+API自己做一個引擎。下面介紹幾種資料庫引擎:
ISAM:ISAM是一個定義明確且歷經時間考驗的資料表格管理方法,它在設計之時就考慮到 資料庫被查詢的次數要遠大於更新的次數。因此,ISAM執行讀取操作的速度很快,而且不佔用大量的記憶體和儲存資源。ISAM的兩個主要不足之處在於,它不 支援事務處理,也不能夠容錯:如果你的硬碟崩潰了,那麼資料檔案就無法恢復了。如果你正在把ISAM用在關鍵任務應用程式裡,那就必須經常備份你所有的實 時資料,通過其複製特性,MYSQL能夠支援這樣的備份應用程式。
MyISAM:MyISAM是MySQL的ISAM擴充套件格式和預設的資料庫引擎。除了提供ISAM裡所沒有的索引和欄位管理的大量功能,MyISAM還使用一種表格鎖定的機制,來優化多個併發的讀寫操作,其代價是你需要經常執行OPTIMIZE TABLE命令,來恢復被更新機制所浪費的空間。MyISAM還有一些有用的擴充套件,例如用來修復資料庫檔案的MyISAMCHK工具和用來恢復浪費空間的 MyISAMPACK工具。MYISAM強調了快速讀取操作,這可能就是為什麼MySQL受到了WEB開發如此青睞的主要原因:在WEB開發中你所進行的大量資料操作都是讀取操作。所以,大多數虛擬主機提供商和INTERNET平臺提供商只允許使用MYISAM格式。MyISAM格式的一個重要缺陷就是不能在表損壞後恢復資料。
HEAP:HEAP允許只駐留在記憶體裡的臨時表格。駐留在記憶體裡讓HEAP要比ISAM和MYISAM都快,但是它所管理的資料是不穩定的,而且如果在關機之前沒有進行儲存,那麼所有的資料都會丟失。在資料行被刪除的時候,HEAP也不會浪費大量的空間。HEAP表格在你需要使用SELECT表示式來選擇和操控資料的時候非常有用。要記住,在用完表格之後就刪除表格。
InnoDB:InnoDB資料庫引擎都是造就MySQL靈活性的技術的直接產品,這項技術就是MYSQL+API。在使用MYSQL的時候,你所面對的每一個挑戰幾乎都源於ISAM和MyISAM資料庫引擎不支援事務處理(transaction process)也不支援外來鍵。儘管要比ISAM和 MyISAM引擎慢很多,但是InnoDB包括了對事務處理和外來鍵的支援,這兩點都是前兩個引擎所沒有的。如前所述,如果你的設計需要這些特性中的一者 或者兩者,那你就要被迫使用後兩個引擎中的一個了。
如果感覺自己的確技術高超,你還能夠使用MySQL+API來建立自己的資料庫引擎。這個API為你提供了操作欄位、記錄、表格、資料庫、連線、安全帳號的功能,以及建立諸如MySQL這樣DBMS所需要的所有其他無數功能。深入講解API已經超出了本文的範圍,但是你需要了解MySQL+API的存在及其可交換引擎背後的技術,這一點是很重要的。估計這個外掛式資料庫引擎的模型甚至能夠被用來為MySQL建立本地的XML提供器(XML provider)。(任何讀到本文的MySQL+API開發人員可以把這一點當作是個要求。)
MyISAM與InnoDB的區別
  InnoDB和MyISAM是許多人在使用MySQL時最常用的兩個表型別,這兩個表型別各有優劣,視具體應用而定。基本的差別為:MyISAM型別不支援事務處理等高階處理,而InnoDB型別支援。MyISAM型別的表強調的是效能,其執行數度比InnoDB型別更快,但是不提供事務支援,而InnoDB提供事務支援已經外部鍵等高階資料庫功能。

以下是一些細節和具體實現的差別:
1.InnoDB不支援FULLTEXT型別的索引。
2.InnoDB 中不儲存表的具體行數,也就是說,執行select count() fromtable時,InnoDB要掃描一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出儲存好的行數即可。注意的是,當count()語句包含where條件時,兩種表的操作是一樣的。
3.對於AUTO_INCREMENT型別的欄位,InnoDB中必須包含只有該欄位的索引,但是在MyISAM表中,可以和其他欄位一起建立聯合索引。
4.DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除。
5.LOAD TABLE FROMMASTER操作對InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,匯入資料後再改成InnoDB表,但是對於使用的額外的InnoDB特性(例如外來鍵)的表不適用。

另外,InnoDB表的行鎖也不是絕對的,假如在執行一個SQL語句時MySQL不能確定要掃描的範圍,InnoDB表同樣會鎖全表,例如updatetable set num=1 where name like “a%”
兩種型別最主要的差別就是Innodb支援事務處理與外來鍵和行級鎖.而MyISAM不支援.所以MyISAM往往就容易被人認為只適合在小專案中使用。
我作為使用MySQL的使用者角度出發,Innodb和MyISAM都是比較喜歡的,但是從我目前運維的資料庫平臺要達到需求:99.9%的穩定性,方便的擴充套件性和高可用性來說的話,MyISAM絕對是我的首選。

原因如下:
1、首先我目前平臺上承載的大部分專案是讀多寫少的專案,而MyISAM的讀效能是比Innodb強不少的。
2、MyISAM的索引和資料是分開的,並且索引是有壓縮的,記憶體使用率就對應提高了不少。能載入更多索引,而Innodb是索引和資料是緊密捆綁的,沒有使用壓縮從而會造成Innodb比MyISAM體積龐大不小。
3、從平臺角度來說,經常隔1,2個月就會發生應用開發人員不小心update一個表where寫的範圍不對,導致這個表沒法正常用了,這個時候MyISAM的優越性就體現出來了,隨便從當天拷貝的壓縮包取出對應表的檔案,隨便放到一個數據庫目錄下,然後dump成sql再導回到主庫,並把對應的binlog補上。如果是Innodb,恐怕不可能有這麼快速度,別和我說讓Innodb定期用匯出xxx.sql機制備份,因為我平臺上最小的一個數據庫例項的資料量基本都是幾十G大小。
4、從我接觸的應用邏輯來說,select count() 和order by是最頻繁的,大概能佔了整個sql總語句的60%以上的操作,而這種操作Innodb其實也是會鎖表的,很多人以為Innodb是行級鎖,那個只是where對它主鍵是有效,非主鍵的都會鎖全表的。
5、還有就是經常有很多應用部門需要我給他們定期某些表的資料,MyISAM的話很方便,只要發給他們對應那表的frm.MYD,MYI的檔案,讓他們自己在對應版本的資料庫啟動就行,而Innodb就需要匯出xxx.sql了,因為光給別人檔案,受字典資料檔案的影響,對方是無法使用的。
6、如果和MyISAM比insert寫操作的話,Innodb還達不到MyISAM的寫效能,如果是針對基於索引的update操作,雖然MyISAM可能會遜色Innodb,但是那麼高併發的寫,從庫能否追的上也是一個問題,還不如通過多例項分庫分表架構來解決。
7、如果是用MyISAM的話,merge引擎可以大大加快應用部門的開發速度,他們只要對這個merge表做一些selectcount(
)操作,非常適合大專案總量約幾億的rows某一型別(如日誌,調查統計)的業務表。
當然Innodb也不是絕對不用,用事務的專案如模擬炒股專案,我就是用Innodb的,活躍使用者20多萬時候,也是很輕鬆應付了,因此我個人也是很喜歡Innodb的,只是如果從資料庫平臺應用出發,我還是會首MyISAM。
另外,可能有人會說你MyISAM無法抗太多寫操作,但是我可以通過架構來彌補,說個我現有用的資料庫平臺容量:主從資料總量在幾百T以上,每天十多億pv的動態頁面,還有幾個大專案是通過資料介面方式呼叫未算進pv總數,(其中包括一個大專案因為初期memcached沒部署,導致單臺數據庫每天處理9千萬的查詢)。而我的整體資料庫伺服器平均負載都在0.5-1左右。

一般來說,MyISAM適合:
(1)做很多count 的計算;
(2)插入不頻繁,查詢非常頻繁;
(3)沒有事務。

InnoDB適合:
(1)可靠性要求比較高,或者要求事務;
(2)表更新和查詢都相當的頻繁,並且表鎖定的機會比較大的情況指定資料引擎的建立
讓所有的靈活性成為可能的開關是提供給ANSI SQL的MySQL擴充套件——TYPE引數。MySQL能夠讓你在表格這一層指定資料庫引擎,所以它們有時候也指的是table formats。下面的示例程式碼表明瞭如何建立分別使用MyISAM、ISAM和HEAP引擎的表格。要注意,建立每個表格的程式碼是相同的,除了最後的 TYPE引數,這一引數用來指定資料引擎。

以下為引用的內容:

複製程式碼程式碼如下:

CREATE TABLE tblMyISAM (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
value_a TINYINT
) TYPE=MyISAM
CREATE TABLE tblISAM (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
value_a TINYINT
) TYPE=ISAM
CREATE TABLE tblHeap (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
value_a TINYINT
) TYPE=Heap

你也可以使用ALTER TABLE命令,把原有的表格從一個引擎移動到另一個引擎。下面的程式碼顯示瞭如何使用ALTER TABLE把MyISAM表格移動到InnoDB的引擎:

以下為引用的內容:

複製程式碼程式碼如下:

ALTER TABLE tblMyISAM CHANGE TYPE=InnoDB

MySQL用三步來實現這一目的。首先,這個表格的一個副本被建立。然後,任何輸入資料的改變都被排入佇列,同時這個副本被移動到另一個引擎。最後,任何排入佇列的資料改變都被送交到新的表格裡,而原來的表格被刪除。

複製程式碼程式碼如下:

ALTER TABLE捷徑

如果只是想把表格從ISAM更新為MyISAM,你可以使用MySQL_convert_table_format命令,而不需要編寫ALTER TABLE表示式。

你可以使用SHOW TABLE命令(這是MySQL對ANSI標準的另一個擴充套件)來確定哪個引擎在管理著特定的表格。SHOW TABLE會返回一個帶有多資料列的結果集,你可以用這個結果集來查詢獲得所有型別的資訊:資料庫引擎的名稱在Type欄位裡。下面的示例程式碼說明了 SHOW TABLE的用法:

複製程式碼程式碼如下:

SHOW TABLE STATUS FROM tblInnoDB

你可以用SHOW CREATE TABLE [TableName]來取回SHOW TABLE能夠取回的資訊。
一般情況下,MySQL會預設提供多種儲存引擎,可以通過下面的檢視:
(1)看你的MySQL現在已提供什麼儲存引擎: mysql> show engines;
(2)看你的MySQL當前預設的儲存引擎: mysql> show variables like ‘%storage_engine%’;
(3)你要看某個表用了什麼引擎(在顯示結果裡引數engine後面的就表示該表當前用的儲存引擎): mysql> show create table 表名;
最後,如果你想使用沒有被編譯成MySQL也沒有被啟用的引擎,那是沒有用的,MySQL不會提示這一點。而它只會給你提供一個預設格式(MyISAM)的表格。除了使用預設的表格格式外,還有辦法讓MySQL給出錯誤提示,但是就現在而言,如果不能肯定特定的資料庫引擎是否可用的話,你要使用SHOW TABLE來檢查表格格式。
更多的選擇意味著更好的效能
用於特定表格的引擎都需要重新編譯和追蹤,考慮到這種的額外複雜性,為什麼你還是想要使用非預設的資料庫引擎呢?答案很簡單:要調整資料庫來滿足你的要求。
可以肯定的是,MyISAM的確快,但是如果你的邏輯設計需要事務處理,你就可以自由使用支援事務處理的引擎。進一步講,由於MySQL能夠允許你在表格這一層應用資料庫引擎,所以你可以只對需要事務處理的表格來進行效能優化,而把不需要事務處理的表格交給更加輕便的MyISAM引擎。對於 MySQL而言,靈活性才是關鍵。

效能測試
所有的效能測試在:Micrisoft window xp sp2 , Intel® Pentinum® M processor 1.6oGHz 1G 記憶體的電腦上測試。
測試方法:連續提交10個query, 表記錄總數:38萬 , 時間單位 s
引擎型別MyISAMInnoDB 效能相差
count 0.00083573.01633609
查詢主鍵 0.005708 0.157427.57
查詢非主鍵 24.01 80.37 3.348
更新主鍵 0.008124 0.8183100.7
更新非主鍵 0.004141 0.02625 6.338
插入 0.004188 0.369488.21
(1)加了索引以後,對於MyISAM查詢可以加快:4 206.09733倍,對InnoDB查詢加快510.72921倍,同時對MyISAM更新速度減慢為原來的1/2,InnoDB的更新速度減慢為原來的1/30。要看情況決定是否要加索引,比如不查詢的log表,不要做任何的索引。
(2)如果你的資料量是百萬級別的,並且沒有任何的事務處理,那麼用MyISAM是效能最好的選擇。
(3)InnoDB表的大小更加的大,用MyISAM可省很多的硬碟空間。

在我們測試的這個38w的表中,表佔用空間的情況如下:

引擎型別MyISAM InnoDB
資料 53,924 KB 58,976 KB
索引 13,640 KB 21,072 KB

佔用總空間 67,564 KB 80,048 KB

另外一個176W萬記錄的表, 表佔用空間的情況如下:
引擎型別MyIsam InnorDB
資料 56,166 KB 90,736 KB
索引 67,103 KB 88,848 KB

佔用總空間 123,269 KB179,584 KB

其他
MySQL 官方對InnoDB是這樣解釋的:InnoDB給MySQL提供了具有提交、回滾和崩潰恢復能力的事務安全(ACID相容)儲存引擎。InnoDB鎖定在行級並且也在SELECT語句提供一個Oracle風格一致的非鎖定讀,這些特色增加了多使用者部署