3

首先,我有以下表结构。

Table Document
  ## DocID ##  ## DocName## ## DuplicateID ##
      1              Doc1        null
      2              Doc2        null
      3              Doc3        null
      4              Doc4         1

Table FolderTree
  ## FolderID ##  ## MemberDocID ##
       1                1
       1                2
       1                3

我有索引DocID, DuplicateID and MemberDocID and FolderID

我的查询是这样的:

SELECT d.* 
from Document d, FolderTree f 
WHERE (d.DocID = f.MemberDocID or d.DuplicateID = f.MemberDocID) and f.FolderID = 1 
GROUP BY d.DocID ;

所以基本上我想从 id 为 1 的文件夹中检索所有文档以及表中的重复文档。group by 用于保持记录的唯一性,即没有文档将被检索两次。

此查询工作正常,但在大量记录中它变得更慢。这是解释输出。


| select type | table | type | possible_keys | key    | rows  |   extra         |

   simple        d     range   PRIMARY,...    PRIMARY   83168   Using temporary..
   simple        f     All     DuplicateIDInx Null      108787  Using join buffer

我担心的是表 f 不使用 DuplicateID 上的索引。我的问题是,为什么会这样?有人可以在这件事上启发我。我正在使用 Mysql 5.x 谢谢 :)

4

3 回答 3

1

您可以改用 in 子句,并使用 distinct 代替 group by。

SELECT distinct d.* 
from Document d
join FolderTree f on f.MemberDocID in (d.DocID, d.DuplicateID)
WHERE f.FolderID = 1

根据SQL Fiddle,这并没有太大变化,除了使连接显式。

duplicateid但是,如果你改变你的

update document
set duplicateid = docid
where duplicateid is null

duplicateid仅选择

SELECT distinct d.* 
from Document d
join FolderTree f on f.MemberDocID = d.DuplicateID
WHERE f.FolderID = 1

将使用索引duplicateid

于 2012-12-07T09:43:17.897 回答
1

试试这个版本:

SELECT d.* 
FROM Document d 
WHERE EXISTS
      ( SELECT *
        FROM FolderTree f 
        WHERE ( d.DocID = f.MemberDocID OR d.DuplicateID = f.MemberDocID )
          AND f.FolderID = 1 
      ) ;

而这个(已编辑):

SELECT d.* 
FROM ( SELECT 1 AS FolderID
     ) AS Parameter
  CROSS JOIN 
     Document d 
WHERE EXISTS
      ( SELECT *
        FROM FolderTree f 
        WHERE f.MemberDocID = d.DocID
          AND f.FolderID = Parameter.FolderID
      ) 
   OR EXISTS
      ( SELECT *
        FROM FolderTree f 
        WHERE f.MemberDocID = d.DuplicateID
          AND f.FolderID = Parameter.FolderID
      ) ;

我还会在FolderTree (FolderID, MemberDocID).

如果您还没有索引Document (DuplicateID),也添加一个。

通过在带有参数的存储过程中编写查询可能会更好地解决额外的要求。

于 2012-12-07T09:38:39.490 回答
1

看起来没有适当的索引。您能否详细说明表结构和查询。

  1. 关于“或 d.DuplicateID = f.MemberID”查询中使用的 f.MemberID 列
  2. explain 显示表 FolderTree 中的 DuplicateIDInx 索引名称。你能从表中提到确切的索引定义吗?
于 2012-12-07T09:42:00.367 回答