2019獨角獸企業重金招聘Python工程師標準>>>
mysql面試題
1. ?各個數據庫存儲引擎區別
mysql的存儲引擎是針對表進行設置的,一個庫的不同表可以設置不同的存儲引擎,mysql默認支持多種存儲引擎,以適用不同領域的數據庫應用需要,主要的幾個數據庫引擎如下:
? MyISAM存儲引擎
5.5之前默認的存儲引擎,不支持事務、不支持外鍵,表級鎖,內存和硬盤空間占用率低,其優勢是訪問速度快,對事務完整性沒有要求,以select、insert為主的應用基本上都可以使用這個引擎;
? InnoDB存儲引擎
5.5之后默認的存儲引擎,提供了具有提交、回滾和奔潰恢復能力的事務安全,支持外鍵并提供了行級鎖,其劣勢在于寫的處理效率相對較低,并且會占用更多的磁盤空間以保留數據和索引;
? MEMORY存儲引擎
使用存于內存中的內容來創建表,MEMORY類型的表數據存于內存訪問非常的快,默認使用HASH索引,一旦數據庫服務重啟或關閉,表中的數據就會丟失;
? MERGE存儲引擎
MERGE存儲引擎是一組MyISAM表組合,這些MyISAM表結構完全相同。MERGE表本身沒有數據,對MERGE表的CRUD操作都是通過內部的MyISAM表進行的;
2. 提高sql 語句效率的技巧
? ?大批量插入數據
????? 大批量數據插入空表,可將表設置成為MyISAM,并通過disable keys將唯一索引關閉;
????? 大批量數據插入非空Innodb表,可采取如下措施提高效率:
????????1. 導入數據時按照主鍵順序排列;
????????2. 導入數據前使用set UNIQUE_CHECKS=0,關閉唯一性校驗,導入后恢復;
????????3. 如果使用了自動提交,建議在導入前執行SET AUTOCOMMIT=0,關閉自動提交,導入后恢復;
? ?優化INSERT 語句
????? 盡量使用多個值表的insert語句,降低連接、關閉的消耗;
????? 將索引文件和數據文件分在不同的磁盤上存放;
????? 從一個文本文件裝入一個表時,使用LOAD DATA INFLIE ,比一般的insert語句快20倍;
? ?查詢優化
????? 盡量減少額外的排序,通過索引直接返回有序數據;where條件和order by使用相同的索引,并且order by的順序與索引順序相同,并且order by的字段都是升序或者都是降序;
????? 盡量只選擇必要的字段,提高sql性能;
????? 能用關聯查詢的不要用子查詢;
????? 對于包含or的查詢語句,如果要利用索引,則or之間的每個條件都必須用到索引,否則應該考慮增加索引;
????? 優化分頁
????? 在索引上完成排序分頁的操作,然后根據主鍵關聯回原表查詢所需的其他列
????? 把limit查詢轉換為某個位置的查詢;
? ?注意不使用索引的情況
????? 如果MySQL估計使用索引比全表掃描更慢,則不使用索引。
????? 用or分隔開的條件,如果or前的條件中的列有索引,而后面的列沒有索引,那么涉及到的索引都不會被用到;
????? 復合索引,如果索引列不是復合索引的第一部分,則不使用索引(即不符合最左前綴;
????? 如果like是以’%’開始的,則該列上的索引不會被使用。
????? 如果列為字符串,則where條件中必須將字符常量值加引號,否則即使該列上存在索引,也不會被使用;
????? not in 、 not exists 、 (<> 不等于 !=)這些操作符不走索引
????? 不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引;
3. 怎么樣做執行計劃分析
通過explain命令獲取mysql如何執行select語句的信息,包括在select語句執行過程中表如何連接和連接的順序;explain分析后的結果解析:
? select_type
????查詢的類型,主要是用于區分普通查詢、聯合查詢、子查詢等復雜的查詢
????? SIMPLE:簡單的select查詢,查詢中不包含子查詢或者union
????? PRIMARY:查詢中包含任何復雜的子部分,最外層查詢則被標記為primary
????? SUBQUERY:在select 或 where列表中包含了子查詢
????? UNION:若第二個select出現在union之后,則被標記為union;若union包含在from子句的子查詢中,外層select將被標記為derived
? type
訪問類型,sql查詢優化中一個很重要的指標,結果值從好到壞依次是:system > const > eq_ref > ref > range > index > ALL一般來說,好的sql 查詢至少達到range 級別,最好能達到ref ;
????? system:表只有一行記錄(等于系統表),這是const類型的特例,平時不會出現,可以忽略不計
????? const:表示通過索引一次就找到了,const用于比較primary key 或者 unique索引。
????? eq_ref:唯一性索引掃描,對于每個索引鍵,表中只有一條記錄與之匹配(1對1);
????? ref:非唯一性索引掃描,返回匹配某個單獨值的所有行。
????? range:索引范圍掃描;
????? index:索引全掃描;
????? ALL:全表掃描;
?possible_keys
查詢涉及到的字段上存在索引,則該索引將被列出,但不一定被查詢實際使用
?key
實際使用的索引,如果為NULL,則沒有使用索引。
?key_len
表示索引中使用的字節數,查詢中使用的索引的長度(最大可能長度),并非實
際使用長度,理論上長度越短越好;
?ref
顯示索引的哪些列;
? rows
根據表統計信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數
?Extra
不適合在其他字段中顯示,但是十分重要的額外信息
優化目標 Tips:
1. 根據需求建立索引
2. 每個查詢都要使用索引以提高查詢效率,至少達到range級別,最好能達到ref;
3. 追求key_len和rows最小;
?
4. mysql 復制的原理
Mysql的復制原理大致如下:
1.主庫在數據提交時會把數據變更作為事件記錄在二進制日志文件Binlog中;可通過sync_binlog控制binlog日志刷新到磁盤的頻率;
2.主庫推送二進制日志文件binlog中的事件到從庫的中繼日志Relay Log,之后從庫根據中繼日志RelayLog重做數據變更操作,通過邏輯復制達到主從庫的數據一致;
3.MySQL通過3個線程來完成主從庫之間的數據同步,其中binlog dump線程跑在主庫上,I/O線程和sql線程跑在從庫上。
當從庫啟動復制時,首先創建I/O線程連接主庫,主庫隨后創建binlog dump線程讀取數據庫事件并發送給I/O線程,I/O線程獲取到事件數據后更新到從庫的中繼日志replay log中去,之后從庫上的sql線程讀取中繼日志中更新的數據庫事件并應用;
?
Mongodb
1. mongodb 與mysql 的區別?
mongodb的本質還是一個數據庫產品,3.0以上版本其穩定性和健壯性有很大提升。它與mysql的區別在于它不會遵循一些約束,比如:sql標準、ACID屬性,表結構等。其主要特性如下:
? 面向集合文檔的存儲:適合存儲Bson(json的擴展)形式的數據;
? 格式自由,數據格式不固定,生產環境下修改結構都可以不影響程序運行;
? 強大的查詢語句,面向對象的查詢語言,基本覆蓋sql語言所有能力;
? 完整的索引支持,支持查詢計劃;
? 支持復制和自動故障轉移;
? 支持二進制數據及大型對象(文件)的高效存儲;
? 使用分片集群提升系統擴展性;
? 使用內存映射存儲引擎,把磁盤的IO操作轉換成為內存的操作;
2. mongoDB 主要使用在什么應用場景?
? MongoDB 的應用已經滲透到各個領域,比如游戲、物流、電商、內容管理、社交、物聯網、視頻直播等,以下是幾個實際的應用案例:
? 游戲場景,使用 MongoDB 存儲游戲用戶信息,用戶的裝備、積分等直接以內嵌文檔的形式存儲,方便查詢、更新
? 物流場景,使用 MongoDB 存儲訂單信息,訂單狀態在運送過程中會不斷更新,以MongoDB 內嵌數組的形式來存儲,一次查詢就能將訂單所有的變更讀取出來。
? 社交場景,使用 MongoDB 存儲存儲用戶信息,以及用戶發表的朋友圈信息,通過地理位置索引實現附近的人、地點等功能
? 物聯網場景,使用 MongoDB 存儲所有接入的智能設備信息,以及設備匯報的日志信息,并對這些信息進行多維度的分析
? 視頻直播,使用 MongoDB 存儲用戶信息、禮物信息等
3. 怎么樣做mongodb 查詢優化
? 第一步 找出慢速查詢
1. 開啟內置的查詢分析器,記錄讀寫操作效率:
????????db.setProfilingLevel(n,{m}),n的取值可選0,1,2;
????? 0是默認值表示不記錄;
????? 1表示記錄慢速操作,如果值為1,m必須賦值單位為ms,用于定義慢速查詢時間的閾值;
????? 2表示記錄所有的讀寫操作;
????????例如:db.setProfilingLevel(1,300)
2. 查詢監控結果
????監控結果保存在一個特殊的蓋子集合system.profile里,這個集合分配了128kb的空間,要確保監控分析數據不會消耗太多的系統性資源;蓋子集合維護了自然的插入順序,可以使用$natural操作符進行排序,如:db.system.profile.find().sort({'$natural':-1}).limit(5)
? 第二步 分析慢速查詢
找出慢速查詢的原因比較棘手,原因可能有多個:應用程序設計不合理、不正確的數據模型、硬件配置問題,缺少索引等;接下來對于缺少索引的情況進行分析:使用explain分析慢速查詢
????例如:db.orders.find({'price':{'$lt':2000}}).explain('executionStats')
????explain的入參可選值為:
????? "queryPlanner" 是默認值,表示僅僅展示執行計劃信息;
????? "executionStats" 表示展示執行計劃信息同時展示被選中的執行計劃的執行情況信息;
????? ?"allPlansExecution" 表示展示執行計劃信息,并展示被選中的執行計劃的執行情況信息,還展示備選的執行計劃的執行情況信息;
? 第三步 解讀explain結果?
queryPlanner(執行計劃描述)
????winningPlan(被選中的執行計劃)
????????stage(可選項:COLLSCAN 沒有走索引;IXSCAN使用了索引)
????rejectedPlans(候選的執行計劃)
executionStats(執行情況描述)
????nReturned (返回的文檔個數)
????executionTimeMillis(執行時間ms)
????totalKeysExamined (檢查的索引鍵值個數)
????totalDocsExamined (檢查的文檔個數)
優化目標 Tips:
1. 根據需求建立索引
2. 每個查詢都要使用索引以提高查詢效率, winningPlan. stage 必須為IXSCAN ;
3. 追求totalDocsExamined = nReturned
4. mongodb 的索引注意事項?
1. 索引很有用,但是它也是有成本的——它占內存,讓寫入變慢;
2. mongoDB通常在一次查詢里使用一個索引,所以多個字段的查詢或者排序需要復合索引才能更加高效;
3. 復合索引的順序非常重要
4. 在生成環境構建索引往往開銷很大,時間也不可以接受,在數據量龐大之前盡量進行查詢優化和構建索引;
5. 避免昂貴的查詢,使用查詢分析器記錄那些開銷很大的查詢便于問題排查;
6. 通過減少掃描文檔數量來優化查詢,使用explai對開銷大的查詢進行分析并優化;
7. 索引是用來查詢小范圍數據的,不適合使用索引的情況:
????? 每次查詢都需要返回大部分數據的文檔,避免使用索引
????? 寫比讀多
5. mongodb 是怎么實現高可用?
Redis
1. 結合項目經驗,說下 redis ?應用場景
? 緩存:合理使用緩存加快數據訪問速度,降低后端數據源壓力
? 排行榜:按照熱度排名,按照發布時間排行,主要用到列表和有序集合
? 計數器應用:視頻網站播放數,網站瀏覽數,使用redis計數
? 社交網絡:贊、踩、粉絲、下拉刷新
? 消息隊列:發布和訂閱
2. redis ?支持數據類型?各有什么特點?
? String(字符串)
string類型是二進制安全的。意思是redis的string可以包含任何數據。比如jpg圖片或者序列化的對象 。string類型是Redis最基本的數據類型,一個redis中字符串value最多可以是512M
? Hash(哈希)
Redis hash 是一個鍵值對集合。Redis hash是一個string類型的field和value的映射表,hash特別適合用于存儲對象。類似Java里面的Map<String,Object>
? List(列表)
Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素導列表的頭部(左邊)或者尾部(右邊),它的底層實際是個鏈表
? Set(集合)
Redis的Set是string類型的無序集合。它是通過HashTable實現實現的,
? zset(sorted set:有序集合)
Redis zset 和 set 一樣也是string類型元素的集合,且不允許重復的成員。不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。zset的成員是唯一的,但分數(score)卻可以重復。
3. 有什么持久化策略?各有什么特點
策略:支持RDB和AOF兩種持久化機制,可以避免因進程退出造成數據丟失,特點如下:
? RDB持久化把當前進程數據生成快照(.rdb)文件保存到硬盤的過程,持久化結束后,用這個臨時文件替換上次持久化的文件,達到數據恢復。 優點在于使用單獨子進程來進行持久化,主進程不會進行任何IO操作,保證了redis的高性能;缺點在于RDB是間隔一段時間進行持久化,如果持久化之間redis發生故障,會發生數據丟失。所以這種方式更適合數據要求不嚴謹的時候;有手動觸發和自動觸發,手動觸發有save和
bgsave兩命令 ;
????? save命令:阻塞當前Redis,直到RDB持久化過程完成為止,若內存實例比較大會造成長時間阻塞,線上環境不建議用它
????? bgsave命令:redis進程執行fork操作創建子線程,由子線程完成持久化,阻塞時間很短(微秒級),是save的優化,在執行redis-cli shutdown關閉redis服x務時,如
果沒有開啟AOF持久化,自動執行bgsave; 顯然bgsave是對save的優化
? AOF:針對RDB不適合實時持久化,redis提供了AOF持久化方式來解決,將“操作 +數據”以格式化指令的方式追加到操作日志文件的尾部,在append操作返回后(已經寫入到文件或者即將寫入),才進行實際的數據變更,“日志文件”保存了歷史所有的操作過程;當server需要數據恢復時,可以直接replay此日志文件,即可還原所有的操作過程
????開啟:redis.conf設置:appendonly yes (默認不開啟,為no)
????默認文件名:appendfilename "appendonly.aof"
5. 介紹下哨兵機制
redis sentinel是一個分布式架構,其中包含了若干個sentinal節點和Redis節點,每個sentinel節點會對數據節點和sentinel節點進行監控,當它發現節點不可達是,會對節點做下線標識。如果大部分sentinal節點認為主節點不可達,sentinal節點之間會進行“協商” ,選舉出來一個sentinal節點完成故障轉義,并同時把這個故障通知到應用方;
6. 介紹 redis ?集群方案?以及其原理
RedisCluster是redis的分布式解決方案,在3.0版本后推出的方案,有效地解決了Redis分布式的需求,當遇到單機內存、并發等瓶頸時,可使用此方案來解決這些問題,一個 redis 集群包含 16384 個哈希槽(hash slot),數據庫中的每個數據都屬于這16384個哈希槽中的一個。集群使用公式(CRC16[key]&16383)函數來計算鍵 key屬于哪個槽。集群中的每一個節點負責處理一部分哈希槽。
7. redis 能做讀寫分離嗎?同步策略是怎么實現的?
redis提供了主從復制和哨兵機制來提高redis服務的健壯性和高可用,但是從嚴格意義上來講,redis并沒有實現讀寫分離,主從復制架構中,主節點用于響應讀寫請求,從節點用于數據備份,如果需要實現讀從從節點讀,應用需要對客戶端進行改造;但在真實場景下一般不需要做此方案,讀寫分離主要應用在磁盤IO比較大的場景,而redis是緩存級別的
同步策略:
redis 2.8版本以上使用psync命令完成同步,過程分“全量”與“部分”復制
a) 全量復制:一般用于初次復制場景(第一次建立SLAVE后全量)
b) 部分復制:網絡出現問題,從節占再次連主時,主節點補發缺少的數據,每次數據增加同步
?
?