假设我有以下 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 查询中检索“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 查询之前立即执行。
这两种方法哪一种更有效?
最佳答案
首先,当你有id .. AUTO_INCREMENT
时在InnoDB表中,PRIMARY KEY(id)
之间没有区别和PRIMARY KEY(id, other_col)
.
第二,你的table2
没有明确的PRIMARY KEY
;这不好'。我们将为您提供一个隐藏的 PK,但它不会像您明确拥有自己的 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开始,并且与上面相同的索引是最佳的。另请注意...因为 table1
中最多有 1 行对于给定的indexnumber
(当 JOINing
时),所有 <>
要做的就是过滤掉一些行。 不需要调整任何索引。
(您的第一个 UPDATE
无效,因为它提到 fieldsix
而没有提及 table2
。)
第二个UPDATE
讨论 SELECT
几乎涵盖了这些内容.
第三个UPDATE
由于日期测试,可能会命中较少的行,但这意味着它与第二个 UPDATE
不同。 -- 因为它不会总是递增 fieldfour
.
关于MySQL UPDATE 性能...更快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51844905/