我有一个看起来像这样的仓库表:
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;
Run Code Online (Sandbox Code Playgroud)
现在,以下查询在查询时间内花费大约0.8 秒,在获取时间花费0.2 秒,总共大约一秒钟.查询返回~67,000行.
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;
Run Code Online (Sandbox Code Playgroud)
向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;
Run Code Online (Sandbox Code Playgroud)
但是,添加"属性"列会将其更改为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;
Run Code Online (Sandbox Code Playgroud)
现在真的要把你的袜子吹掉.而不是txtProperty1,使用txtProperty2将时间更改为0.8s fetch,24s查询!
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;
Run Code Online (Sandbox Code Playgroud)
这两列在它们所拥有的数据类型上几乎完全相同:大多数都是非空的,并且都没有被索引(不是那些应该会产生差异).为了确保表本身是健康的,我对它进行了分析/优化.
这对我来说真的很神秘.我可以看到为什么只在select子句中添加列可以略微增加获取时间,但它不应该改变查询时间,尤其不会显着.我会很感激任何导致这种放缓的想法.
编辑 - 更多数据点
SELECT*实际上优于txtProperty2 - 0.8s查询,8.4s提取.太糟糕了我无法使用它,因为获取时间(预计)太长了.
我承认这有点猜测,但我会尝试一下。
您将id第一个字段作为主键。我不是 100% 确定 MySQL 如何执行聚集索引的查找,但有理由怀疑,对于任何给定的 ID,都有一些指向具有该 ID 的记录的“指针”。
当所有先前的字段都具有固定宽度时,找到字段的开头相对容易。所有BIGINT(20)字段都有一个定义的大小,这使得数据库引擎可以轻松找到给定指向记录开头的指针的字段;这是一个简单的计算。同样,第一个字段的开头VARCHAR(255)也很容易找到。但之后,因为字段是VARCHAR字段,所以数据库引擎必须考虑数据才能找到下一个字段的开始,这比简单地计算该字段应该在哪里要慢得多。因此,对于 txtProperty1 之后的任何字段,您都会遇到此问题。
如果将所有VARCHAR(255)字段都更改为CHAR(255)字段会发生什么?您的查询很可能会快得多,尽管代价是为每个CHAR(255)字段使用最大存储空间,而不管它实际包含的数据如何。
| 归档时间: |
|
| 查看次数: |
971 次 |
| 最近记录: |