日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
我們該如何設(shè)計數(shù)據(jù)庫(五)

最近真是忙翻天了,該是有三個月沒寫博客了。

10年積累的網(wǎng)站制作、成都做網(wǎng)站經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站策劃后付款的網(wǎng)站建設(shè)流程,更有環(huán)江免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

這次的需求是在Mongo的使用中碰到的,但是我覺得把這個需求放進(jìn)傳統(tǒng)的RDBMS中更易于理解。需求是這樣的:假設(shè)你數(shù)據(jù)庫使用的是Sqlserver,有一張表,500W條數(shù)據(jù),你要做一個隨機在表中選擇一條數(shù)據(jù)的功能。

假設(shè)本文所探討的數(shù)據(jù)結(jié)構(gòu)如圖(聚集索引在Pk上,UserName上加了非聚集索引):

你的***反應(yīng)大概是:哎呀媽呀忒巧了,正好主鍵使用的是Int自增的,我只用生成一個隨機數(shù),然后找這個隨機數(shù)對應(yīng)的主鍵就好了

實現(xiàn)的步驟大概是:

①返回數(shù)據(jù)庫中ID的***值IdMax

②生成1到IdMax中間一個的隨機數(shù) int random = new Random().Next(1,IdMax);

③使用UserID = random作為條件查詢

④如果沒有查詢到數(shù)據(jù),則重新生成一個隨機數(shù),再次查找(因為某個UserID的數(shù)據(jù)可能被刪除了)

這種方法簡單,暴力,但是有一個致命的問題:我這里在建表的時候為了說明這種方法,所以主鍵使用的是Int,但是在大多數(shù)我所知道的生產(chǎn)環(huán)境中,其實是用Guid的。這個致命的問題會直接導(dǎo)致上面的那個方法不可用。

至于為什么大多數(shù)我所知道的生產(chǎn)環(huán)境中用Guid而不用Int,我下一篇會做出對比。

既然Int在使用Guid作為主鍵的時候不能用,那么我們就用Row_Number吧。Sqlserver必然是支持Row_Number的,貌似Oracle和MySql中也有類似概念(不確定,問同事得到了肯定答復(fù),沒有深究)。

實現(xiàn)的步驟大概是:

①返回數(shù)據(jù)庫中數(shù)據(jù)的總條數(shù)count

②生成1到count中間一個的隨機數(shù) int random = new Random().Next(1,count);

③查找Row_Number = random的那條數(shù)據(jù)

但是Row_Number有個極其不好的地方,就是查詢越后面的數(shù)據(jù)越慢,越吃資源。但凡是將數(shù)據(jù)有序儲存的數(shù)據(jù)庫基本都有這個問題,比如說下面兩條語句:

 
 
 
 
  1. select * from 
  2. (SELECT  UserID,UserName,Password,Sex,City,ROW_NUMBER()OVER(ORDER BY CURRENT_TIMESTAMP) as Number  
  3.   FROM [User_db].[dbo].[Users] ) as query  
  4.   where query.Number = 20  
  5.     
  6.     
  7. select * from 
  8. (SELECT  UserID,UserName,Password,Sex,City,ROW_NUMBER()OVER(ORDER BY CURRENT_TIMESTAMP) as Number  
  9.   FROM [User_db].[dbo].[Users] ) as query  
  10.   where query.Number = 5000000 

***條查Row_Number=20的數(shù)據(jù),logical reads 5.elapsed time = 58 ms.

第二條查Row_Number=5000000的數(shù)據(jù),logical reads 90208.elapsed time = 900 ms.

可以明顯的看出,后者的邏輯讀次數(shù)多了太多,而運行速度也慢了不少。如果這個功能比較頻繁使用,比如說這是向用戶隨機推薦好用的功能,那么這個將會成為一個性能瓶頸

有的網(wǎng)友說使用這句:

 
 
 
 
  1. SELECT TOP 1 * FROM Users ORDER BY NEWID()  

這個運行出來結(jié)果是正確的,但是效率卻大打折扣。比如說我查到了第1336793條數(shù)據(jù),logical reads 90208,elapsed time = 3026 ms

查看執(zhí)行計劃,發(fā)現(xiàn)Sort占用了98%:

有沒有比Row_Number更好一點的方法?

答案是在表中再加一列Random列,使得數(shù)據(jù)結(jié)構(gòu)變更成這樣:

在添加數(shù)據(jù)的時候,就生成一個隨機數(shù)插入進(jìn)來。按照本篇的例子來說,一開始可以生成0到一億之間的隨機數(shù)插入。注意,要在Random上加索引。

實現(xiàn)的步驟大概是:

①插入數(shù)據(jù)的時候添加一個隨機

②生成一個隨機數(shù),查詢 select top(1) * from Users where Random > 隨機數(shù)

③這個查詢的結(jié)果可能會有多條(但不會很多),再在這個多條數(shù)據(jù)中隨機篩選其一(使用Linq可以很方便的實現(xiàn),不贅述)

好了,基本說完了,請允許我在結(jié)尾賣個萌:聰明的讀者,開動腦筋,您還有更好的方法么?如果有,請留言。


新聞標(biāo)題:我們該如何設(shè)計數(shù)據(jù)庫(五)
網(wǎng)頁網(wǎng)址:http://www.dlmjj.cn/article/djhooso.html