MySQL UPDATE 性能...更快
Posted
技术标签:
【中文标题】MySQL UPDATE 性能...更快【英文标题】:MySQL UPDATE Performance ...which is faster 【发布时间】:2018-08-14 15:26:46 【问题描述】:假设我有以下 2 个 mysql 表:
CREATE TABLE Table1
(
IndexNumber INT UNSIGNED NOT NULL AUTO_INCREMENT,
FieldOne TINYINT UNSIGNED NOT NULL,
FieldTwo VARCHAR(180) NOT NULL,
FieldThree DATE,
FieldFour INT,
PRIMARY KEY (IndexNumber, FieldThree),
UNIQUE KEY (FieldOne, FieldTwo)
) ENGINE=InnoDB;
和
CREATE TABLE Table2
(
IndexNumber INT UNSIGNED NOT NULL,
FieldFive TINYINT UNSIGNED NOT NULL,
FieldSix TINYINT UNSIGNED NOT NULL,
FOREIGN KEY (IndexNumber) REFERENCES Table1 (IndexNumber),
KEY (IndexNumber),
KEY (FieldFive, FieldSix)
) ENGINE=InnoDB;
现在,我想做几个查询来检索一些匹配的记录,并且在每个 SELECT 查询之后我想更新匹配的记录,以便明天才能再次检索它们。
SELECT 查询如下:
SELECT table1.fieldone,
table1.fieldtwo
FROM table2
INNER JOIN table1
ON table2.indexnumber = table1.indexnumber
WHERE table2.fieldfive = 1
AND table2.fieldsix = 2;
SELECT table1.fieldone,
table1.fieldtwo
FROM table2
INNER JOIN table1
ON table2.indexnumber = table1.indexnumber
WHERE table2.fieldfive = 1
AND table2.fieldsix = 3
AND table1.fieldthree <> Curdate();
我的问题是——在每个 select 查询之后更新匹配记录以使下一个 SELECT 查询不匹配它的最快方法是什么?
我可以在 SELECT 查询中检索“IndexNumber”字段,然后我可以按如下方式执行 UPDATE 查询,传入“IndexNumber”字段值:
UPDATE table1
SET fieldthree = Curdate(),
fieldfour = (fieldfour + 1)
WHERE indexnumber IN (...indexnumbers...)ve = 1
AND table2.fieldsix = 3
AND table1.fieldthree <> curdate();
或者我可以从 SELECT 查询中重复 WHERE,并希望缓存使其更快:
UPDATE table2
INNER JOIN table1
ON table2.indexnumber = table1.indexnumber
SET table1.fieldthree = Curdate(),
table1.fieldfour = ( table1.fieldfour + 1 )
WHERE table2.fieldfive = 1
AND table2.fieldsix = 2;
UPDATE table2
INNER JOIN table1
ON table2.indexnumber = table1.indexnumber
SET table1.fieldthree = Curdate(),
table1.fieldfour = ( table1.fieldfour + 1 )
WHERE table2.fieldfive = 1
AND table2.fieldsix = 3
AND table1.fieldthree <> Curdate()
AND table1.fieldthree <> Curdate();
请注意,UPDATE 查询将在 SELECT 查询之后和下一个 SELECT 查询执行之前立即执行。
这两种方法哪一种更有效?
【问题讨论】:
TLDR。你为什么不测试这两种方法而不是问我们? 向我们展示数据库架构、示例数据、当前和预期输出。请阅读How-to-Ask 这里是START 了解如何提高问题质量并获得更好答案的好地方。 How to create a Minimal, Complete, and Verifiable example 尝试在rextester.com 中创建示例。 现在我读到并不清楚更新是发生在 Query1 和 Query2 之间还是在 Query2 之后。也不清楚你想做什么,因为没有任何数据或预期的结果。 最快通常是理论上的,直到您使用 your 系统配置在 your 硬件上对其进行测试。对于在 128GB 高度优化的 64 核 MySQL 服务器上工作的人可能会在更适中的系统上表现得很糟糕。 好吧,很公平,我希望有人能有见解,但一旦我运行了一些测试,我会回来发布更新...... 【参考方案1】:首先,当您在 InnoDB 表中有 id .. AUTO_INCREMENT
时,PRIMARY KEY(id)
和 PRIMARY KEY(id, other_col)
之间没有区别。
第二,你的table2
没有明确的PRIMARY KEY
;这是不好的'。将为您提供隐藏的 PK,但它不会像明确拥有自己的那样“好”。
对于这个选择:
INNER JOIN table1 ON table2.indexnumber = table1.indexnumber
WHERE table2.fieldfive = 1
AND table2.fieldsix = 2;
它将以table2
开头,因为有过滤(WHERE
)。最佳索引是
table2: INDEX(fieldfive, fieldsix, -- in either order
indexnumber) -- to make the index "covering"
table1: (indexnumber) -- it's already the PK, so good
对于这个选择:
INNER JOIN table1 ON table2.indexnumber = table1.indexnumber
WHERE table2.fieldfive = 1
AND table2.fieldsix = 3
AND table1.fieldthree <> Curdate(); -- not easy to optimize
再次,它将从 table2 开始,并且与上面相同的索引是最佳的。另一个注意事项...由于给定的indexnumber
(当JOINing
)在table1
中最多有1 行,所以<>
会过滤掉一些行。 没有需要调整任何索引。
(您的第一个UPDATE
无效,因为它提到fieldsix
而没有提及table2
。)
第二个UPDATE
几乎涵盖了讨论SELECT
。
第三个UPDATE
可能会由于日期测试而命中更少的行,但这意味着它不与第二个UPDATE
相同——因为它不会总是增加@987654342 @。
【讨论】:
以上是关于MySQL UPDATE 性能...更快的主要内容,如果未能解决你的问题,请参考以下文章