标题不够明确......
我每小时都在运行一个查询来准备MEMORY表,然后用于下一个小时的高密集流量。现在查询看起来像:
INSERT INTO tmp_table
SELECT DISTINCT SQL_NO_CACHE
B.*, G.node
FROM books B
RIGHT JOIN book_genres G on G.asin=B.asin
WHERE EXISTS
(
SELECT 1 FROM genres K WHERE K.node=G.node
)
AND...[nothing special here]
所以books表只保存带有asin的PRIMARY KEY的书籍数据。 book_genres包含asin和node字段,包含许多在站点的各个部分中使用的节点。但是,tmp_table只需要包含流派表中的节点子集,即子查询。希望这足以在不发布完整模式的情况下完成。
我们现在想要使某些类型相互排斥。这意味着在构建tmp_table后执行此操作:
# Delete records that should have been excluded
DELETE T FROM tmp_table T INNER JOIN
(
SELECT N.* FROM tmp_table N INNER JOIN
(
SELECT DISTINCT ASIN FROM tmp_table
INNER JOIN genres ON genres.node=tmp_table.node
WHERE isFiction=1
) F
ON F.asin=N.asin
INNER JOIN genres ON genres.node=N.node
WHERE genres.isNonFiction=1
) D
USING (asin, node)
WHERE D.asin=T.asin AND D.node=T.node
因此,如果asin属于isFiction = 1的类型,则删除所有nonFiction = 1的类型。
但这感觉很难看:使用查询添加数据然后再次删除它。有没有什么方法可以将它组合成一个查询以避免双通。或者我只为自己工作,鉴于(经过一些调整和编辑),上述工作可以很快地完成。
任何想法都会受到赞赏,谢谢。
添加了示例:
books table:
asin title price etc...
B111111111 Book1 $0.99 ....
B222222222 Book2 $0.99 ....
B333333333 Book2 $0.99 ....
book_genres table:
asin node
B111111111 1111
B111111111 2222
B111111111 3333
B111111111 5555
B222222222 1111
B222222222 3333
B222222222 4444
B333333333 1111
B333333333 2222
genres table:
node name isFiction isNonFiction
1111 Bestsellers 0 0
2222 Romance 1 0
3333 Biographies 0 1
4444 History 0 1
所以在运行INSERT INTO之后,tmp_table将如下所示:
asin title node
B11111111 Book1 1111
B11111111 Book1 2222
B11111111 Book1 3333
B22222222 Book2 1111
B22222222 Book2 3333
B22222222 Book2 4444
B33333333 Book3 1111
B33333333 Book3 2222
Book1没有节点5555的记录,因为它不在流派表中,我们在tmp_table中不需要它。其他所有内容几乎都是数据的非规范化,因为WHERE在数据库中识别出数以千计的数百本书的子部分,这样可以更快地使用。
下一步确保如果书籍具有isFiction节点,则删除该书籍的所有isNonFiction节点。
运行DELETE后,tmp_table的最终结果为:
asin title node
B11111111 Book1 1111
B11111111 Book1 2222
B22222222 Book2 1111
B22222222 Book2 3333
B22222222 Book2 4444
B33333333 Book3 1111
B33333333 Book3 2222
唯一的区别是Book1删除了节点3333,因为Book1位于2222节点,其中isFiction = 1且节点3333具有isNonFiction = 1。 Book2未更改,因为它不包含isFiction节点。同样,Book3没有变化,因为它不包含isNonFiction节点。
在这个阶段,它正在使用这个实现,虽然运行时间从大约20多秒增加到大约40倍。真的没有意外,因为DELETE有点复杂。这可能是一个不错的解决方案,但如果其他人有一个想法可以使整个事情变得更简单或更快,我会很高兴。
...标记
答案 0 :(得分:0)
这很难看。它工作正常,直到数据库上有任何其他重大负载,然后这一切都非常缓慢。这主要取决于服务器的IO限制,但更简单的方法是将isfiction和isNonFiction放入MEMORY表中,然后DELETE语句可以如下所示:
DELETE tmp_table FROM tmp_table
INNER JOIN
(
SELECT ASIN, MAX( isFiction ) AS isFiction, MAX( isNonFiction ) AS isNonFiction
FROM tmp_table
GROUP BY ASIN
HAVING isFiction =1
AND isNonFiction =1
) D
WHERE D.ASIN=tmp_table.ASIN AND tmp_table.isNonFiction=1
在测试中,这将使整个过程从大约90秒降低到10秒。