一個搜索框瘸羡,幾個包含網(wǎng)頁漩仙、新聞、圖片犹赖、視頻等在內(nèi)的選項:這恐怕是目前搜索引擎留給我們大多數(shù)人的印象吧队他。然而,我們今天不講搜索引擎峻村,而是搜索技術(shù)哦~麸折!
搜索,亦稱查找粘昨,是以 “搜索的精準度”(內(nèi)容匹配度)和“搜索效率”(搜索耗時)雙向界定的技術(shù)磕谅。技術(shù)開發(fā)中的耗時偏指,程序員構(gòu)建搜索程序時的“項目管理時間”和“程序可用的用戶等待時間”雾棺。
較之Hadoop、Spark和NoSQL數(shù)據(jù)庫如火如荼的發(fā)展衬浑,搜索——這一最原始捌浩、最有用的大數(shù)據(jù)技術(shù)仿佛備受冷落。當被寄予厚望的Spark等技術(shù)工秩,隨著發(fā)展?jié)u顯”非萬能“的疲態(tài)尸饺,許多人的關(guān)注點便又重歸搜索的優(yōu)化設(shè)計≈遥可從以下幾個方面著手:
一浪听、數(shù)據(jù)庫優(yōu)化設(shè)計
二、索引文件讀取方式的優(yōu)化設(shè)計
三眉菱、查找算法的優(yōu)化設(shè)計
四迹栓、SQL語句的優(yōu)化設(shè)計
五、客戶端代碼的優(yōu)化設(shè)計
下面俭缓,我們就展開詳細論述
一克伊、數(shù)據(jù)庫優(yōu)化設(shè)計
1.對表建立分區(qū)
2.針對表中字段建立索引
3.優(yōu)化存儲
…
二酥郭、索引文件讀取方式的優(yōu)化設(shè)計
1.大文件讀取方式的設(shè)計
散列映射方式的設(shè)計:通過散列或其他方式,將大文件映射為多個小文件愿吹,以減輕服務器負擔不从。
多處理方式靈活設(shè)計:對大數(shù)據(jù)映射而來的小文件,選擇合適的處理方式:單個逐步處理犁跪,并行式處理椿息,多臺機器分布式處理等
2.文件讀取中緩存方式的優(yōu)化
統(tǒng)量處理:一次性將所有數(shù)據(jù)放入緩存中,并進行處理
批量處理:將數(shù)據(jù)分批次放入緩存坷衍,并分批次進行處理寝优。簡言之便是,放一部分惫叛,取一部分倡勇,一批一批處理。
兩種處理方式各有利弊嘉涌,應視情況予以選擇妻熊。但除此之外,我們還是會有一些發(fā)揮的空間仑最,比如緩存的分區(qū)塊或分片處理扔役,通過分割出來的緩存區(qū)塊對不同數(shù)據(jù)的分別處理,實際上便相當于設(shè)計出了一個并行處理模式警医。
3.流類選擇及數(shù)據(jù)傳輸方式設(shè)計
數(shù)據(jù)傳輸方式亿胸,對應著程序語言相關(guān)聯(lián)的流類,并視程序語言的不同预皇,流處理也會有所區(qū)別侈玄。一般,主流程序語言對于流類的封裝都比較成熟吟温,使得程序語言對性能的優(yōu)化影響并不大序仙。但是,鑒于語言在系統(tǒng)搭建之初便已被選好鲁豪,后期更改的空間并不大潘悼。
4.大數(shù)據(jù)讀取的輸出測試設(shè)計
通過每隔一段時間的輸出測試,以及時定位問題爬橡。
三治唤、查找算法的優(yōu)化設(shè)計
對于大文件,散列查找和二分查找算法糙申,仍是目前主流的實現(xiàn)方式宾添。
鑒于散列算法的限制條件,在散列函數(shù)的選取中應著重考慮如下問題:
1、散列函數(shù)的選取
2辞槐、沖突處理方式
3掷漱、P值的選取
4、大文件分割
5榄檬、排序算法
其中卜范,對于散列函數(shù)及沖突,P值的選取非常關(guān)鍵鹿榜,越大的P值越能減少沖突海雪,但對應著大量內(nèi)存的浪費,所以舱殿,龐大的數(shù)據(jù)與有限的內(nèi)存間便存在一個不小的矛盾奥裸。“分而治之”是個值得考慮的策略沪袭,即將大文件按照一定規(guī)則分割成多個小文件單獨處理湾宙,但這樣一來,不同文件就必須進行單獨的排序和查找冈绊,也會多消耗一定的時間侠鳄,具體要看我們?nèi)绾螜?quán)衡利弊。
四死宣、SQL語句的優(yōu)化設(shè)計
數(shù)據(jù)庫對海量數(shù)據(jù)進行查詢伟恶,我們主要考慮的是盡量避免進行全表查詢。具體到SQL語句上來說毅该,一篇文章對此進行了詳細的闡述博秫,具體如下(來源:http://blog.fufuok.com/Article/507.aspx):
1.對查詢進行優(yōu)化,應首先考慮在?where?及?order by?涉及的列上建立索引眶掌,而盡量避免全表掃描挡育。
2.盡量避免在?where?子句中對字段進行?null?值判斷,以降低引擎放棄使用索引而進行全表掃描的幾率朴爬,如:
select id from t where num is null
可以在num上設(shè)置默認值0静盅,確保表中num列沒有null值,然后這樣查詢:
select id from t where num=0
3.盡量避免在?where?子句中使用!=或<>操作符寝殴,以降低引擎放棄使用索引而進行全表掃描的幾率。
4.盡量避免在?where?子句中使用or?來連接條件明垢,以降低引擎放棄使用索引而進行全表掃描的幾率蚣常,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=20
5.in?和?not in?也要慎用,否則會導致全表掃描痊银,如:
select id from t where num in(1,2,3)
對于連續(xù)的數(shù)值抵蚊,能用?between?就不要用?in?了:
select id from t where num between 1 and 3
6.下面的查詢也將導致全表掃描:
select id from t where name like '?c%'
若要提高效率,可以考慮全文檢索。
7.?如果在?where?子句中使用參數(shù)贞绳,也會導致全表掃描谷醉。因為SQL只有在運行時才會解析局部變量,但優(yōu)化程序不能將訪問計劃的選擇推遲到運行時冈闭;它必須在編譯時進行選擇俱尼。然 而,如果在編譯時建立訪問計劃萎攒,變量的值還是未知的遇八,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:
select id from t where num=@num
可以改為強制查詢使用索引:
select id from t with(index(索引名)) where num=@num
8.盡量避免在?where?子句中對字段進行表達式操作耍休,以降低引擎放棄使用索引而進行全表掃描的幾率刃永。如:
select id from t where num/2=100
應改為:
select id from t where num=100*2
9.盡量避免在where子句中對字段進行函數(shù)操作,以降低引擎放棄使用索引而進行全表掃描的幾率羊精。如:
select id from t where substring(name,1,3)='abc'--name以abc開頭的id
select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id
應改為:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'
10.盡量避免在?where?子句中的“=”左邊進行函數(shù)斯够、算術(shù)運算或其他表達式運算,以降低引擎放棄使用索引而進行全表掃描的幾率喧锦。
(注:部分內(nèi)容整合自網(wǎng)絡)