【问题标题】:MySQL Query with inner join takes long time带有内部连接的 MySQL 查询需要很长时间
【发布时间】:2014-03-04 19:46:43
【问题描述】:

尽管表中没有太多产品,但以下查询花费的时间太长。 如果我在没有内部连接的情况下查询它,一切都很好。能否请人帮忙找出问题或优化此查询。

SELECT P.ID AS ID, 
IFNULL(P.MIN_PRICE, 0) AS PRICE_MIN, 
IFNULL(P.MAX_PRICE, 0) AS PRICE_MAX, 
IFNULL(P.STORE_COUNT, 0) AS STORE_COUNT, 
P.TITLE AS TITLE, 
'' AS DETAIL, 
P.MANUFACTURER
FROM PRODUCT P 
INNER JOIN PRODUCT P1 on (P1.ID=P.PARENT_ID) OR (P.ID=P1.ID) WHERE P.PARENT_ID=0 AND P.ISVALID='Y' AND P1.CATEGORY_ID IN (2040)

这是表结构:

CREATE TABLE IF NOT EXISTS `PRODUCT` (
`ID` int(11) unsigned NOT NULL DEFAULT '0',
`CATEGORY_ID` int(11) unsigned NOT NULL DEFAULT '0',
`TITLE` varchar(255) NOT NULL DEFAULT ' ',
`FILENAME` varchar(255) DEFAULT ' ',
`MANUFACTURER` int(11) unsigned NOT NULL DEFAULT '0',
`EAN_UPC` varchar(100) DEFAULT '',
`MIN_PRICE` decimal(9,2) DEFAULT '0.00',
`MAX_PRICE` decimal(9,2) DEFAULT '0.00',
`STORE_COUNT` int(11) unsigned DEFAULT '0',
`ISVALID` enum('Y','N') NOT NULL DEFAULT 'Y',
`FEATURES_SELECTED` enum('Y','N') NOT NULL DEFAULT 'N',
`PARENT_ID` int(11) DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `IndexCATEGORY_ID` (`CATEGORY_ID`),
KEY `IndexFILENAME` (`FILENAME`),
KEY `IndexMANUFACTURER` (`MANUFACTURER`),
KEY `IndexISVALID` (`ISVALID`),
KEY `IndexCOMP1` (`ID`,`ISVALID`),
KEY `IndexORDER_BY` (`CATEGORY_ID`,`ISVALID`,`STORE_COUNT`),
KEY `IndexTOTAL` (`CATEGORY_ID`,`ISVALID`),
KEY `IndexPARENT_ID` (`PARENT_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

编辑: 我尝试获取一个类别或其子类别中的所有产品。有些产品有父母:比如说一条 10 种不同尺寸的牛仔裤。其他人没有父母,但他们也不是孩子(孤儿):比如说一条没有任何变体的围巾。现在,如果我删除 OR,我只会得到牛仔裤,因为满足 join 中的第一个条件。但它不会退回围巾,尽管它是该类别的有效产品。

编辑: @BhupeshC 这里有一些数据(CATEGORY_ID=2040):

ID   PARENT_ID TITLE 
1    0         Dress blue
2    1         Dress blue XS
3    1         Dress blue S
4    1         Dress blue M
5    0         Dress Yellow
6    5         Dress Yellow M
7    5         Dress Yellow L
8    5         Dress Yellow XL
9    0         Scarf men
10   0         Scarf women

其余列可以设置为默认值。 预期结果:

ID   PARENT_ID TITLE 
1    0         Dress blue
5    0         Dress Yellow
9    0         Scarf men
10   0         Scarf women

编辑:当我查看数据时,我想有人会说只需查询 parent_id=0 的产品。请不要那样做。因为我刚刚简化了查询。在原始查询中,可以根据只能在子产品上找到的信息过滤数据,但这会使问题更加复杂。例如。我只想展示尺寸为 XL 的产品。 但是 DrewB 的 UNION 方法可能有效,我只是想看看是否有更好的解决方案。

感谢您的帮助。

【问题讨论】:

  • 您能否解释一下您要执行的操作,以便可以在不使用 OR 的情况下重新编写此查询?

标签: mysql join


【解决方案1】:

您的问题是内部联接中的 OR。它使它成为一个更昂贵的连接。您可以使用 EXPLAIN https://dev.mysql.com/doc/refman/5.0/en/using-explain.html 查看影响。

【讨论】:

  • 谢谢,但我需要 OR,因为我只想显示父母,但有些产品没有父母。有什么方法可以在没有 OR 的情况下获得我需要的东西?
  • 很难说不知道更多关于数据的信息,但有时您可以使用 UNION 来删除 OR。因此,编写 2 个不同的查询(OR 的每个部分一个)并将结果联合起来。
【解决方案2】:

试试这个:-

SELECT P.ID AS ID, 
IFNULL(P.MIN_PRICE, 0) AS PRICE_MIN, 
IFNULL(P.MAX_PRICE, 0) AS PRICE_MAX, 
IFNULL(P.STORE_COUNT, 0) AS STORE_COUNT, 
P.TITLE AS TITLE, 
'' AS DETAIL, 
P.MANUFACTURER
FROM PRODUCT P 
LEFT JOIN PRODUCT P1 on (P1.ID=P.PARENT_ID) WHERE P.PARENT_ID=0 AND P.ISVALID='Y' AND P1.CATEGORY_ID IN (2040)

【讨论】:

  • 如果我这样做,它不会退回孤儿产品。在这种情况下,我不需要任何连接,一个简单的查询就足够了。
  • 能否提供一些具有预期结果集的示例数据?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
  • 2013-12-19
相关资源
最近更新 更多