我有一张仓库的桌子,看起来是这样的:
CREATE TABLE Warehouse (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
eventId BIGINT(20) UNSIGNED NOT NULL,
groupId BIGINT(20) NOT NULL,
activityId BIGINT(20) UNSIGNED NOT NULL,
... many more ids,
"txtProperty1" VARCHAR(255),
"txtProperty2" VARCHAR(255),
"txtProperty3" VARCHAR(255),
"txtProperty4" VARCHAR(255),
"txtProperty5" VARCHAR(255),
... many more of these
PRIMARY KEY ("id")
KEY "WInvestmentDetail_idx01" ("groupId"),
... several more indices
) ENGINE=INNODB;
现在,下面的查询花费了大约0.8s的查询时间和0.2s的获取时间,总共大约一秒钟。查询返回约67000行。
SELECT eventId
FROM Warehouse
WHERE accountId IN (10, 8, 13, 9, 7, 6, 12, 11)
AND scenarioId IS NULL
AND insertDate BETWEEN DATE '2002-01-01' AND DATE '2011-12-31'
ORDER BY insertDate;
向select子句添加更多的id实际上根本不会改变性能。
SELECT eventId, groupId, activityId, insertDate
FROM Warehouse
WHERE accountId IN (10, 8, 13, 9, 7, 6, 12, 11)
AND scenarioId IS NULL
AND insertDate BETWEEN DATE '2002-01-01' AND DATE '2011-12-31'
ORDER BY insertDate;
但是,添加“property”列会将其更改为0.6s获取时间和1.8s查询时间。
SELECT eventId, txtProperty1
FROM Warehouse
WHERE accountId IN (10, 8, 13, 9, 7, 6, 12, 11)
AND scenarioId IS NULL
AND insertDate BETWEEN DATE '2002-01-01' AND DATE '2011-12-31'
ORDER BY insertDate;
现在真的让你大吃一惊。使用txtproperty2而不是txtproperty1将时间更改为0.8s fetch,24s query!
SELECT eventId, txtProperty2
FROM Warehouse
WHERE accountId IN (10, 8, 13, 9, 7, 6, 12, 11)
AND scenarioId IS NULL
AND insertDate BETWEEN DATE '2002-01-01' AND DATE '2011-12-31'
ORDER BY insertDate;
这两列在它们所保存的数据类型上几乎完全相同:大部分都是非空的,而且两列都没有索引(这无论如何都不应该有区别)。为了确保表本身是健康的,我对它运行了analyze/optimize。
这让我很迷惑。我可以理解为什么在select子句中添加列只会稍微增加获取时间,但它不应该更改查询时间,特别是不会显著地更改查询时间。我很想知道是什么导致经济放缓。
编辑-更多数据点
select*实际上优于txtproperty2-0.8s查询,8.4s获取。可惜我不能用它,因为取货时间(预计)太长了。
最佳答案
innodb引擎的mysqldocumentation建议,如果varchar
数据不适合页面(即b树结构的节点),那么信息将在溢出页面上被引用。所以在宽仓库表上,可能txtProperty1
在页面上,txtProperty2
在页面外,因此需要额外的I/O来检索。
不太清楚为什么SELECT *
更好;它可能能够利用顺序读取数据的优势,而不是在磁盘上随意选择。