我有一个SQLite数据库,其中有一个带有库存的表(约27000行)和一个带有股价的表(约6000万行)。我需要获取每只股票的最新股价日期。最初,我使用
SELECT stockID, MAX(PriceDate) AS MaxDate FROM StockPrices
GROUP BY stockID
解释查询计划给出以下信息:
"0" "0" "0" "SCAN TABLE StockPrices USING COVERING INDEX sqlite_autoindex_StockPrices_1"
但是,这大约需要21秒钟才能运行。然后我尝试了这个:
SELECT stockID, (SELECT PriceDate FROM StockPrices AS sp
WHERE s.stockID= sp.stockID
ORDER BY PriceDate DESC
) AS MaxDate FROM Stocks AS s
解释查询计划给出以下信息:
"0" "0" "0" "SCAN TABLE Stocks AS s USING COVERING INDEX Index_Stocks_CompanyID"
"0" "0" "0" "EXECUTE CORRELATED SCALAR SUBQUERY 1"
"1" "0" "0" "SEARCH TABLE StockPrices AS sp USING COVERING INDEX sqlite_autoindex_StockPrices_1 (StockListingID=?)"
现在我可以在3毫秒内得到结果。
这大大减少了计算时间,我想更好地了解这种性能差异的出处。 我给人的印象是max()函数会非常有效,但是显然在某些情况下,可以进行更快的查询。这两个查询都使用相同的覆盖索引,因此从查询计划中我无法说出为什么这么快。
这些是用于相关表和索引的create语句:
CREATE TABLE StockPrices (StockID INTEGER NOT NULL,PriceDate NUMERIC NOT NULL,PxClose NUMERIC NOT NULL,Volume INTEGER,Source TEXT,DateAdded NUMERIC DEFAULT (JulianDay(CURRENT_TIMESTAMP)), PRIMARY KEY (StockID, PriceDate, PxClose, Volume))
CREATE TABLE Stocks (StockID INTEGER NOT NULL PRIMARY KEY ON CONFLICT ABORT,CompanyID INTEGER NOT NULL REFERENCES Companies (CompanyID),PrimaryListing INTEGER DEFAULT 0,Delisted INTEGER DEFAULT 0,ExchangeID INTEGER NOT NULL REFERENCES Exchanges (ExchangeID),CountryID INTEGER NOT NULL REFERENCES Countries (CountryID),IBKRSymbol TEXT,ISIN TEXT)
CREATE INDEX Index_StockListings_CompanyID ON StockListings (CompanyID)