国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 網(wǎng)站 > 建站經(jīng)驗(yàn) > 正文

如何應(yīng)對(duì)并發(fā)(1) - 關(guān)于數(shù)據(jù)索引

2024-04-25 20:17:10
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

曹政(caoz)如何應(yīng)對(duì)并發(fā)系列文章

如何應(yīng)對(duì)并發(fā)(3) - 需求裁剪

如何應(yīng)對(duì)并發(fā)(2) - 請(qǐng)求合并及異步處理

如何應(yīng)對(duì)并發(fā)(1) - 關(guān)于數(shù)據(jù)索引

-------------------------------------------------------------------------------------------------

前兩天收到一個(gè)消息是這樣說(shuō)的,一個(gè)學(xué)生去面試,題目赫然就是從瀏覽器輸入url到網(wǎng)頁(yè)打開(kāi),都發(fā)生了什么。這個(gè)學(xué)生特別開(kāi)心,因?yàn)橛嗛喠宋业墓娞?hào),所以對(duì)這類問(wèn)題早有準(zhǔn)備。希望他能順利拿到心儀的offer。

參見(jiàn)舊文 一則經(jīng)典技術(shù)面試題目的解讀

書歸正傳,應(yīng)對(duì)并發(fā),其實(shí)從整體架構(gòu)來(lái)說(shuō)分很多部分,比如常見(jiàn)的,存儲(chǔ)層的i/o優(yōu)化,網(wǎng)絡(luò)層負(fù)載均衡,通訊層的連接池等等,不過(guò)我這里不講這些。不講這些的原因第一呢,是這些我基本都不太會(huì);第二呢,是在實(shí)踐過(guò)程中發(fā)現(xiàn),特別是創(chuàng)業(yè)公司,中小企業(yè),一般最容易出問(wèn)題,也是最難處理的,往往是數(shù)據(jù)庫(kù)方面的問(wèn)題。

非技術(shù)人員往往會(huì)認(rèn)為,負(fù)載高了,請(qǐng)求多了,加服務(wù)器加硬件不就完了? 如果是只是應(yīng)用程序處理,常見(jiàn)的負(fù)載均衡方案很成熟,加加硬件的確可以快速,有效的分擔(dān)負(fù)載,提高支撐能力;但是且慢,通常到了數(shù)據(jù)庫(kù)這里,如果你前期設(shè)計(jì)不合理,或者對(duì)這類問(wèn)題考慮不全,那么,加硬件,很遺憾,是沒(méi)用的。

我們常說(shuō)運(yùn)維中要關(guān)注所謂的單點(diǎn)隱患,什么是單點(diǎn)隱患呢?就是這個(gè)點(diǎn)一旦崩潰,無(wú)法實(shí)現(xiàn)自動(dòng)的災(zāi)難容錯(cuò)響應(yīng),從而導(dǎo)致全盤崩潰。一般比如說(shuō)web服務(wù)器,負(fù)載均衡輪詢,一臺(tái)出問(wèn)題了,系統(tǒng)會(huì)自動(dòng)將負(fù)載轉(zhuǎn)移到其他服務(wù)器,那么數(shù)據(jù)庫(kù)可以不可以呢?其實(shí)不是不可以,但是就比較需要做好設(shè)計(jì),否則很可能直接就死在這個(gè)環(huán)節(jié)上。而發(fā)展趨勢(shì)不錯(cuò)的創(chuàng)業(yè)公司死在數(shù)據(jù)庫(kù)的并發(fā)能力上的案例,可以說(shuō),比比皆是。


再插一些題外話,如果你還是學(xué)生,你有意未來(lái)往互聯(lián)網(wǎng)技術(shù)領(lǐng)域發(fā)展,那么數(shù)據(jù)結(jié)構(gòu)這么課特別的重要,特別的關(guān)鍵。我上大學(xué)的時(shí)候糊里糊涂,選中了這門課卻天天翹課,工作后特別后悔。就算你不想從事技術(shù),而只是想從事一些產(chǎn)品方面的工作,我個(gè)人建議有可能也認(rèn)真學(xué)習(xí)一下這門課,目前不少互聯(lián)網(wǎng)公司都希望產(chǎn)品經(jīng)理有一點(diǎn)技術(shù)背景,這樣和技術(shù)溝通的時(shí)候會(huì)更順暢一些。對(duì)研發(fā)工作的跟進(jìn)也會(huì)能理解更多一些。

今天的第一課,我們先要對(duì)數(shù)據(jù)索引和查詢效率有個(gè)基本認(rèn)識(shí),連基本優(yōu)化都做不好去講什么架構(gòu)是沒(méi)意義的。

第一個(gè)問(wèn)題,為什么一條查詢語(yǔ)句,使用了數(shù)據(jù)索引會(huì)提高效率?

以及,通過(guò)一條SQL語(yǔ)句,能否估算出其執(zhí)行開(kāi)銷和最佳索引選擇?

熟悉數(shù)據(jù)結(jié)構(gòu)同學(xué)大概知道,一般數(shù)據(jù)庫(kù)的索引大概是btree,b+tree,類似這樣的結(jié)構(gòu),那么現(xiàn)在非關(guān)系型數(shù)據(jù)庫(kù)特別流行,也就是所謂的key-value數(shù)據(jù)庫(kù),最求極端效率,通常是 hash結(jié)構(gòu)的數(shù)據(jù)索引。但其實(shí)這些,我認(rèn)為對(duì)于我這樣笨的人來(lái)說(shuō),通常,只需要理解最基本的概念就行,最基本的是什么呢?就是數(shù)據(jù)索引提供了一種有序,在有序的情況下,進(jìn)行檢索,二分法效率最高,n條記錄中定位查詢開(kāi)銷是 log2(N),(hash索引效率更高,但不提供關(guān)系型查詢,應(yīng)用場(chǎng)景比較受局限)。 那么所謂的btree結(jié)構(gòu)也好,或其他的類似結(jié)構(gòu)也好,把握一個(gè)原則,接近二分法的查詢效率,因?yàn)槿绻鲆粋€(gè)完全有序的隊(duì)列,那么插入,刪除,修改需要做的操作開(kāi)銷太大了,大家可以思考一下,所以才會(huì)有人設(shè)計(jì)樹(shù)形結(jié)構(gòu),兼顧查詢和更新操作。理解這一點(diǎn)對(duì)理解整個(gè)數(shù)據(jù)查詢效率和索引結(jié)構(gòu),幫助極大。

簡(jiǎn)單復(fù)習(xí)就是,查詢效率的關(guān)鍵是有序,二分,反過(guò)來(lái)理解就是,無(wú)需遍歷所有數(shù)據(jù),即可實(shí)現(xiàn)快速的定位。

這里就引出了一個(gè)特別經(jīng)典的題目,ip地址反查。

應(yīng)用場(chǎng)景非常常見(jiàn),你上一個(gè)什么旅游訂票的網(wǎng)站,社區(qū),或者上百度,該網(wǎng)站都希望立即知道你的地理位置,從而基于你的位置定向投放內(nèi)容,比如當(dāng)?shù)鼐频辏蛘弋?dāng)?shù)氐谋镜貜V告。網(wǎng)站一般是獲取用戶的ip地址,然后在ip->地區(qū)的對(duì)應(yīng)表里去查詢比對(duì),通常,ip - 地區(qū)的對(duì)應(yīng)表,有大約十萬(wàn)到數(shù)十萬(wàn)條記錄(看地區(qū)粒度),格式是 ipstart, ipend, area 這樣的數(shù)據(jù)結(jié)構(gòu)。如果用純粹的SQL查詢是

select * from iparea where $ip between ipstart and ipend;

在早期mysql及大部分?jǐn)?shù)據(jù)庫(kù)是不支持between and 中使用索引的,據(jù)說(shuō)最新版本已經(jīng)提供了支持,但是最近幾年沒(méi)有從事技術(shù),沒(méi)有測(cè)試,不知道效率如何,那么在早期,如果數(shù)據(jù)查詢,這樣一條SQL,無(wú)法使用索引,就要遍歷所有結(jié)果,這個(gè)開(kāi)銷是不能忍受的,(雖然不用1秒就可以執(zhí)行出結(jié)果,但是開(kāi)銷依然比較大,一秒鐘可以處理的查詢最多幾十次,而我們的要求是,一秒鐘幾千次!)

那么這個(gè)問(wèn)題的特點(diǎn)是什么呢,ip地址區(qū)間表并不是經(jīng)常變化的,比較固定,那么在這種情況下,其實(shí)不用數(shù)據(jù)庫(kù)都可以,一個(gè)完全排好序的隊(duì)列放在內(nèi)存里,程序用二分法來(lái)查詢,每秒種處理幾千個(gè)非常輕松(這程序不用教了吧),當(dāng)然,其實(shí)還有更極端效率的處理途徑,這里不展開(kāi),有興趣的同學(xué)自己思考。

此處插播一條廣告,目前國(guó)內(nèi)最好最權(quán)威的ip地址區(qū)間表來(lái)自于高春輝,利益相關(guān),我超過(guò)15年的好基友,互聯(lián)網(wǎng)傳奇人物,需要定期更新ip地址區(qū)間表的建議找他購(gòu)買,聯(lián)系方式,去微博搜索 高春輝 。

再插播一個(gè)題外話,我在微博上說(shuō)過(guò),百度最應(yīng)該購(gòu)買,這是不耍流氓的情況下提升收入最快的方法,可能很多人不理解,其實(shí)百度有很多廣告投放是按地區(qū)投放的,04年底 我剛進(jìn)百度的時(shí)候閑著沒(méi)事就給升級(jí)了一個(gè)ip地區(qū)對(duì)應(yīng)表,把大量未知地區(qū)的ip定位到了已知地區(qū),很多分地區(qū)投放的廣告展現(xiàn)率一下子就提高了,收入自然隨之增長(zhǎng),這玩意雖然看上去不是什么高大上的算法,但是勤更新對(duì)收入影響杠杠的。(小貼士,國(guó)際ip管理機(jī)構(gòu)會(huì)不定期釋放ip資源出來(lái)給新的網(wǎng)絡(luò)設(shè)施和上網(wǎng)服務(wù)商,所以在最近這些年,ip地址區(qū)間表還是不斷的擴(kuò)充中)

第二個(gè)問(wèn)題,從一個(gè)常見(jiàn)SQL如何確定索引的構(gòu)成

以下所有案例均以mysql 為例,原因是,這個(gè)我熟悉。

非mysql可能部分語(yǔ)法不同,但邏輯和思路相同。

發(fā)現(xiàn)有一個(gè)簡(jiǎn)單問(wèn)題很多人會(huì)答錯(cuò),一個(gè)SQL可以用到幾個(gè)索引?很多人會(huì)說(shuō)是多個(gè),其實(shí)是一個(gè),目前一些第三方的數(shù)據(jù)引擎似乎開(kāi)始支持一條SQL使用多索引了,比如我前幾天看淘寶公開(kāi)的那個(gè)開(kāi)源數(shù)據(jù)結(jié)構(gòu)的文檔,從官方博客的描述中似乎有這樣的提法,但是我最近確實(shí)很懶惰也脫離技術(shù),所以沒(méi)有去測(cè)試和仔細(xì)研究,這個(gè)留給有興趣的同學(xué)吧,我還是回頭說(shuō)通常,我們用mysql或其他常見(jiàn)數(shù)據(jù)庫(kù)的,一個(gè)查詢只能用到一個(gè)索引;但是這里要強(qiáng)調(diào)的是,一個(gè)索引可以用到多個(gè)字段,也就是所謂的復(fù)合索引。

那么,按照剛才提到的,基于有序這個(gè)概念,如何理解索引的使用和效率呢?特簡(jiǎn)單,你就把索引當(dāng)作是一個(gè)有序數(shù)列放在腦子里,然后思考這個(gè)SQL,這個(gè)條件子句和排序子句,能否在這個(gè)索引的連續(xù)范圍內(nèi)精確命中結(jié)果,也就是所謂索引命中率高,這個(gè)查詢就效率高,如果無(wú)法在索引這個(gè)有序數(shù)列連續(xù)范圍內(nèi)精確命中,查詢效率就不高。

那有人說(shuō)了,索引并不是真的有序數(shù)列啊,我說(shuō)的是一種模擬的思考方式,這樣思考效率最高,當(dāng)然,必須案例說(shuō)話。

比如一個(gè)社區(qū),我希望用戶進(jìn)來(lái),就能看到本地的用戶,當(dāng)然,是最新在線的,否則都是死用戶就無(wú)法交流了。

SQL select * from user where area='$area' order by lastlogin desc limit 30;

(這個(gè) limit 特別重要)

稍微懂一點(diǎn)索引的同學(xué)都應(yīng)該知道,正確的索引是area+lastlogin 復(fù)合索引,那么,我們把這個(gè)思考方式推演一下。

如果只把a(bǔ)rea當(dāng)作索引會(huì)怎樣,數(shù)據(jù)庫(kù)會(huì)把符合這個(gè)area的所有結(jié)果拿出來(lái),然后按照l(shuí)astlogin排好序給你,這樣就要遍歷所有符合這個(gè)area的用戶記錄;

如果只把lastlogin作為索引會(huì)如何,我們想象,lastlogin是一個(gè)有序的數(shù)列,數(shù)據(jù)庫(kù)會(huì)從最后一條開(kāi)始往前挨條遍歷,每條都去比對(duì)area是不是符合查詢條件,直到數(shù)出30條,遍歷結(jié)束,請(qǐng)注意,不是全部遍歷,在這里,如果area 是個(gè)熱門城市,比如上海,北京,可能遍歷200次左右就出結(jié)果了,效率很快,但如果是個(gè)冷門城市,可能要遍歷幾千條幾萬(wàn)條結(jié)果,甚至全部數(shù)據(jù)表遍歷都湊不出符合條件的30條。這樣效率就要命了。 所以用lastlogin為索引,效率存在風(fēng)險(xiǎn)。

那么兩個(gè)我都建立索引呢?這個(gè)mysql只會(huì)選擇一個(gè)索引,我記得不同數(shù)據(jù)庫(kù)版本的選擇策略都不同(實(shí)戰(zhàn)中遇到過(guò)測(cè)試服務(wù)器用的索引很正確,線上服務(wù)器使用了錯(cuò)誤索引,因?yàn)閿?shù)據(jù)庫(kù)版本不同),所以我給不出肯定的答案,但是有一點(diǎn),兩個(gè)索引沒(méi)有意義,都不是最優(yōu)解。

那么如果把lastlogin+area建立索引呢?你們?cè)O(shè)想一下,兩個(gè)字段拼在一起,作為有序數(shù)列,然后數(shù)據(jù)庫(kù)去查詢的時(shí)候,lastlogin+area,這時(shí)候area是沒(méi)用的后綴,在排序中根本體現(xiàn)不出他存在的意義,和單獨(dú)lastlogin索引是完全一樣的。

而area+lastlogin呢,把兩個(gè)字段拼接然后排好序后,看這條SQL在這個(gè)數(shù)列中查詢的體現(xiàn),所命中的完全是連續(xù)的30條,也就是數(shù)據(jù)庫(kù)只遍歷30條索引記錄即完成搜索,效率最好。

這段有點(diǎn)

主站蜘蛛池模板: 什邡市| 南木林县| 宜阳县| 清水县| 靖远县| 龙泉市| 柯坪县| 长海县| 汉中市| 曲沃县| 江山市| 溧阳市| 郓城县| 炎陵县| 郴州市| 海晏县| 东光县| 卓尼县| 藁城市| 安康市| 黄石市| 南康市| 临湘市| 正蓝旗| 龙川县| 涟源市| 怀集县| 若尔盖县| 冀州市| 渑池县| 油尖旺区| 侯马市| 香河县| 浦县| 西乌珠穆沁旗| 甘洛县| 扎兰屯市| 新兴县| 辰溪县| 雷州市| 宁都县|