MySql查询中的OR问题

时间:2015-11-16 05:47:44

标签: mysql

当我使用OR增强查询时,我遇到了性能问题。

查询的简化版本如下。使用表单,用户可以向查询添加多个条件以缩小其结果。

 SELECT DISTINCT DocL.DocumentLineId
 FROM DocumentLine            AS  DocL
 INNER JOIN DocumentField     AS DocF00 ON DocF00.DocumentLineId   = DocL.DocumentLineId
 INNER JOIN DocumentField     AS DocF01 ON DocF01.DocumentLineId   = DocL.DocumentLineId

 WHERE ( DocF00.DocumentType_FieldId = '383' AND DocF00.DocumentFieldValue = '113563' )
    OR ( DocF01.DocumentType_FieldId = '383' AND DocF01.DocumentFieldValue = '46910043' )
 ;

如果我在没有最后一行的情况下运行查询,则需要不到一秒的时间。 使用查询中的OR行大约需要45秒。

DocumentLine表有大约75,000条记录。

DocumentField表有大约110万条记录。

除了各个ID的两个表上的主键之外,DocumentField还有DocumentLineId,DocumentType_FieldId和DocumentFieldValue上的索引。

所有Id字段为INT(11)。

DocumentType_FieldId大约有150个可能的值。

DocumentFieldValue是VARCHAR(250),几乎可以包含任何内容。

有关如何优化此查询的任何建议都将不胜感激。

ETA:效果数据作为链接上的图片。

Explain without the OR line

Explain with OR line added

CREATE TABLE  `DocumentLine` (  
`DocumentLineId` int(11) NOT NULL AUTO_INCREMENT,  
`DocumentLineSequence` int(11) NOT NULL,  
`DocumentLineCoordinates` varchar(45) DEFAULT NULL,  
`DocumentLineElementId` int(11) DEFAULT NULL,  
`DocumentType_LineId` int(11) NOT NULL,  
`DocumentSectionId` int(11) NOT NULL,  
PRIMARY KEY (`DocumentLineId`),  
KEY `fk_DocumentLine_DocumentSection` (`DocumentSectionId`),  
KEY `fk_DocumentLine_DocumentTypeLine` (`DocumentType_LineId`),  
CONSTRAINT `fk_DocumentLine_DocumentSection` FOREIGN KEY (`DocumentSectionId`) REFERENCES `DocumentSection` (`DocumentSectionId`) ON DELETE NO ACTION ON UPDATE CASCADE,  
CONSTRAINT `fk_DocumentLine_DocumentTypeLine` FOREIGN KEY (`DocumentType_LineId`) REFERENCES `DocumentTypeLine` (`DocumentTypeLineId`) ON DELETE NO ACTION ON UPDATE NO ACTION);

CREATE TABLE  `DocumentField` (  
`DocumentFieldId` int(11) NOT NULL AUTO_INCREMENT,  
`DocumentFieldValue` varchar(255) DEFAULT NULL,  
`DocumentFieldCoordinates` varchar(45) DEFAULT NULL,  
`DocumentType_FieldId` int(11) NOT NULL,  
`DocumentLineId` int(11) NOT NULL,  
`ElementId` int(11) NOT NULL,  
PRIMARY KEY (`DocumentFieldId`),  
KEY `idx_DocumentType_FieldId` (`DocumentType_FieldId`),  
KEY `idx_DocumentLineId` (`DocumentLineId`),  
KEY `idx_DocumentFieldValue` (`DocumentFieldValue`),  
KEY `idx_TypeId_Value` (`DocumentType_FieldId`,`DocumentFieldValue`));

PS:这是我第一次就Stack Overflow提出问题,如果我没有遵循协议,请提前道歉。

1 个答案:

答案 0 :(得分:0)

我认为你不需要两个连接来获得你想要的东西。 试试这个:

SELECT DISTINCT dl.DocumentLineId
FROM DocumentField AS df
INNER JOIN DocumentLine AS dl ON dl.DocumentLineId = df.DocumentLineId
WHERE df.DocumentType_FieldId = 383
    AND (
           df.DocumentFieldValue = '113563'
        OR df.DocumentFieldValue = '46910043'
    )
;

如果您只想从 DocumentLine 表中获取 DocumentLineId ,那么您根本不需要加入:

SELECT DISTINCT df.DocumentLineId
FROM DocumentField AS df
WHERE df.DocumentType_FieldId = 383
    AND (  
           df.DocumentFieldValue = '113563'
        OR df.DocumentFieldValue = '46910043'
    )
;

如果我们想要搜索不同的字段类型( DocumentType_FieldId )并使用 LIKE ,也没有问题:

SELECT DISTINCT df.DocumentLineId
FROM DocumentField AS df
WHERE ( df.DocumentType_FieldId = '383' AND df.DocumentFieldValue LIKE '%113563%' )
   OR ( df.DocumentType_FieldId = '384' AND df.DocumentFieldValue LIKE '%46910043%' )
   OR ( df.DocumentType_FieldId = '123' AND df.DocumentFieldValue LIKE '%SMITH%' )
   OR ( df.DocumentType_FieldId = '234' AND df.DocumentFieldValue LIKE '%what%ever%' )
;

如果您需要更多字段,可以将其与 DocumentLine 表联系起来。你几乎可以立刻得到结果。