以下MySQL查询的速度有多慢?
我已经尝试过将索引添加到DocumentRevision.document和Document.status但是它仍然需要永远执行查询(似乎如果按顺序进行查询,查询会加快速度)。还有另一种更有效的方法来实现相同的结果吗?该查询将获取数据库中所有可用文档的所有最新修订版本。有两张桌子。文档和文档修订。文档表只包含id和status字段,而DocumentRevision包含所有数据和“document”id字段,以便它知道哪个文档的修订版本。
SELECT rev.document as documentId, rev.id as revId, rev.name as name,
rev.dateCreated as dateCreated, rev.documentOrder as documentOrder
FROM (
SELECT Document.id as docId, MAX(DocumentRevision.id) as maxRevId
FROM Document, DocumentRevision
WHERE Document.id = DocumentRevision.document AND Document.status = 0
GROUP BY Document.id
) AS x
INNER JOIN DocumentRevision as rev on rev.document = x.docId
AND rev.id = x.maxRevId
ORDER BY dateCreated DESC;
答案 0 :(得分:0)
您有两种选择:
SELECT dr.*
FROM (
SELECT document, MAX(id) AS maxid
FROM documentRevision
GROUP BY
document
) drd
JOIN documentRevision dr
ON dr.id = drd.maxid
JOIN document d
ON (d.id, d.status) = (drd.document, 0)
和
SELECT dr.*
FROM document d
JOIN documentRevision dr
ON dr.id =
(
SELECT id
FROM documentRevision dri
WHERE dri.document = d.id
ORDER BY
document DESC, id DESC
LIMIT 1
)
第一个很可能是最有效的,除非你每个文档都有很多版本。
在documentRevision (document, id)
上创建一个复合索引(按此顺序),以使查询快速运行。
答案 1 :(得分:0)
查看您的要求:
有两张桌子。文档和文档修订。文件表 只包含id和status字段,而DocumentRevision包含 所有数据和“文档”id字段,以便它知道哪个 文件的修订版。
你的代码,我写了另一个没有subselect的查询。只需在document.ID和documentRevision.document上选择一个适当的索引就可以获得更好的连接性能。
SELECT rev.document docID, MAX(rev.id) revID, rev.name revName, rev.dateCreated dateCreated, rev.documentOrder docOrder
FROM DocumentRevisin as rev, Document as doc
WHERE doc.status = 0 AND doc.id = rev.document
GROUP BY rev.document, rev.name revName, rev.dateCreated dateCreated, rev.documentOrder docOrder
答案 2 :(得分:0)
我怀疑如果结果很大,带有GROUP BY
的子查询可能会导致一些执行计划问题;您可能希望在没有子查询的情况下尝试查询。
(Document.id
,DocumentRevision.document
和DocumentRevision.status
上的索引会有所帮助。)
SELECT rev.document as documentId, rev.id as revId, rev.name as name,
rev.dateCreated as dateCreated, rev.documentOrder as documentOrder
FROM Document doc
JOIN DocumentRevision rev
ON doc.id=rev.document
LEFT JOIN DocumentRevision rev2
ON rev.document = rev2.document AND rev.id < rev2.id
WHERE doc.status=0 AND rev2.id IS NULL
ORDER BY dateCreated DESC;
SQLfiddle to show identical results。请注意没有子查询的查询的简单计划。
答案 3 :(得分:0)
您的查询多次使用联接中的documentRevision表。肯定有优化的空间。
在其他DBMS(例如Teradata或MS SQL服务器中,这可以通过'{1}}形式的'窗口聚合'功能来完成。
MySQL没有窗口聚合功能。 但是可以使用参数完成相同的操作:
sum(1) over(partition by rev.document order by rev.id desc)
这样,DBMS不会加入表两次,只加入一次然后进行排序。
我没有MySQL环境来测试它,但是根据需要调整它。我希望这会有所帮助。 还请在Document.id和DocumentRevision.document上有索引以优化连接。