假设我有以下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查询执行之前立即执行。
这两种方法中哪个更有效?
答案 0 :(得分:0)
首先,当InnoDB表中有id .. AUTO_INCREMENT
时,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
在indexnumber
中最多有1行(当JOINing
时),所有<>
所要做的就是过滤掉一些行。 无需调整任何索引。
(您的第一个UPDATE
无效,因为它提及fieldsix
却没有提及table2
。)
讨论UPDATE
几乎涵盖了第二个SELECT
。
由于日期测试,第三个UPDATE
可能会命中更少的行,但这意味着它与第二个UPDATE
是不相同-因为它不会总是递增fieldfour
。