當您有 60 億行並且需要從 ID 列表中查詢行時,使用哪個數據庫?
我們目前正在研究儲存城市之間道路距離的案例。現在我們有60億這樣的距離。
我們現在在 SQL Server 中的結構是我們有一個
float
代表城市之間的關係。例如,如果我們有一個在表中包含Id
1的城市和在同一個表中包含 2 的城市,則距離為 1 到 2 的行將如下所示。該列已編入索引。Locations``Id``1.2,'1000 miles'
所以要得到從城
1000
到城的距離2535
,我們就在1000.2535
裡面找Distances
。除了獲得單個距離外,我們還需要從這 60 億行中選擇 1000 個距離組:
SELECT id ,distance FROM Distances WHERE id IN (1000.2535, 1.2, ...)
現在我們只在本地機器上測試了 SQL Server,它為我們提供了大約 300 毫秒的 1000 行查詢,但只有當我們設置 50 毫秒超時時(這對於來自多個使用者的大量並行請求是必需的) ,如果不使用 50 毫秒超時,它只會呈指數增長,例如第一個 300 毫秒,第二個 500 毫秒,第三個 800 毫秒,等等。
現在我們來看看專門針對
mget
.所以我的問題是:
- 對於這樣的案例,您會推薦哪個數據庫?
- 除了我們想到的其他一些想法(例如將城市 ID 分成兩個不同的列等)之外,您還會推薦什麼?
- 優化此類數據庫的最佳方法是什麼?
我在這裡的假設是
FLOAT
代替實際的複合鍵會減慢查詢引擎創建正確估計的能力。因此,不要使用“聰明”列,而是使用複合主鍵:
CREATE TABLE Country ( CountryCd CHAR(3) NOT NULL --ISO Country Code ,Name VARCHAR(50) NOT NULL ,CONSTRAINT PK_Country PRIMARY KEY (CountryCd) ,CONSTRAINT AK_Country UNIQUE (Name) ) ; CREATE TABLE Subdivision --State/province/region/county etc. ( CountryCd CHAR(3) NOT NULL ,SubdivisionCd CHAR(3) NOT NULL --ISO subdivision code ,Name VARCHAR(50) NOT NULL ,CONSTRAINT FK_Subdivision_Division_Of_Country FOREIGN KEY (CountryCd) REFERENCES Country (CountryCd) ,CONSTRAINT PK_Subdivision PRIMARY KEY (CountryCd, SubdivisionCd) ,CONSTRAINT AK_Subdivision UNIQUE (CountryCd, Name) ) ; CREATE TABLE City ( CityId INT NOT NULL ,CountryCd CHAR(3) NOT NULL ,SubdivisionCd CHAR(3) NOT NULL ,Name VARCHAR(50) NOT NULL ,CONSTRAINT FK_City_Located_In_Subdivision FOREIGN KEY (CountryCd, SubdivisionCd) REFERENCES Subdivision (CountryCd, SubdivisionCd) ,CONSTRAINT PK_City PRIMARY KEY (CityId) ,CONSTRAINT AK_City UNIQUE (CountryCd, SubdivisionCd, Name) ) ; CREATE TABLE CityRoadDistance ( SourceCityId INT NOT NULL ,DestinationCityId INT NOT NULL ,RoadDistance INT NOT NULL ,CONSTRAINT FK_CityDistance_From_City FOREIGN KEY (SourceCityId) REFERENCES City (CityId) ,CONSTRAINT FK_CityDistance_To_City FOREIGN KEY (DestinationCityId) REFERENCES City (CityId) ,CONSTRAINT PK_CityDistance PRIMARY KEY (SourceCityId, DestinationCityId) ,CONSTRAINT CK_CityDistance_SourceCityId_LT_DestinationCityId CHECK (SourceCityId < DestinationCityId) --Enforces only one record per city pair ) ;
很容易找到單個距離:
SELECT RoadDistance FROM CityDistance WHERE SourceCityId = 7 AND DestinationCityId = 235
但正如您所說,次要要求是在 50 毫秒內返回 1,000。您將無法使用
IN
,因此您需要為該WHERE
子句建立一個列表(例如(SourceCityId = 7 AND DestinationCityId = 235) OR (SourceCityId = 1345 AND DestinationCityId = 2934)
…)。這應該允許查詢引擎查看事物並說:“哦,我只需要執行 1,000 次搜尋”並相對快速地返回您的數據。但是對於 50 毫秒或更短的時間,您將需要一些非常快的 SSD 或已經記憶體在記憶體中的頁面。
替代方案類似於記憶體中的鍵值儲存。這會在一定程度上減少編譯和查找時間,但我會嘗試使用實際的複合鍵並查看會發生什麼。