首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >mysql查询需要1+分钟才能完成

mysql查询需要1+分钟才能完成
EN

Stack Overflow用户
提问于 2021-11-12 08:43:17
回答 1查看 88关注 0票数 0

此查询

代码语言:javascript
复制
 SELECT * FROM kp_landing_page lp
            WHERE lp.parent = '7' AND (
                SELECT COUNT(*) FROM kp_landing_page_product lpp
                    WHERE lpp.landing_page_id = lp.landing_page_id
                      AND lpp.productid = '6176'
            ) != 0

大约需要1+分钟才能完成,我试着这样重写它

代码语言:javascript
复制
 SELECT * FROM kp_landing_page lp
            INNER JOIN (SELECT COUNT(*) FROM kp_landing_page_product lpp
                  WHERE lpp.landing_page_id = lp.landing_page_id
                    AND lpp.productid = '6176') != 0
            WHERE lp.parent = '7'

虽然这要快得多(3-4秒),但它没有满足我所需的数据,即使所有的表都保持不变,并且在phpmyadmin中执行这个查询会给我提供与旧查询相同的数据。它只会给出以下错误

代码语言:javascript
复制
The current selection does not contain a unique column. 
  Functions such as raster edits, checkboxes, Edit, 
  Copy and Delete are not available.

关于如何优化这一点有什么想法吗?不一定要非常快,1+,慢一分钟。

编辑

对旧查询运行explain

代码语言:javascript
复制
EXPLAIN SELECT * FROM kp_landing_page lp WHERE lp.parent = '7'
          AND ( SELECT COUNT(*) FROM kp_landing_page_product lpp
                    WHERE lpp.landing_page_id = lp.landing_page_id
                      AND lpp.productid = '6176' ) != 0

为我提供了以下内容

代码语言:javascript
复制
1 id
PRIMARY select_Type
lp table
ALL type 
NULL possible_keys 
NULL keys
NULL key_len
NULL ref
233 rows
Using where extra
---
2
DEPENDENT SUBQUERY
lpp
ref
landing_page_id
landing_page_id
4
kerstpakketonline.lp.landing_page_id
437
Using where

编辑2

更多信息

这段代码(PHP)就是速度减慢的地方

代码语言:javascript
复制
    $landingPages = array();
    $qGetMainPages = $connection->query("SELECT *
             FROM kp_landing_page WHERE parent = 0");

    foreach ($qGetMainPages->rows as $mainPage) {
        $qGetSubPages = $connection->query("
            SELECT  lp.* FROM kp_landing_page lp
            WHERE lp.parent = '" . (int)$mainPage['landing_page_id'] . "' AND (
                SELECT COUNT(*) FROM kp_landing_page_product lpp
            WHERE lpp.landing_page_id = lp.landing_page_id 
               AND lpp.productid = " . (int)$row['productID'] . "
            ) != 0
        ");


        foreach ($qGetSubPages->rows as $subPage) {
            $landingPages[$mainPage['title']][] = $subPage['title'];
        }
    }

似乎正在对每个产品执行x数量的查询,从而导致o(n)问题?

编辑3

使用SHOW CREATE TABLE on both tables

-- kp_landing_page_product

kp_landing_page_product CREATE TABLE kp_landing_page_product ( id int(11) NOT NULL AUTO_INCREMENT, landing_page_id int(11) NOT NULL, productid int(11) NOT NULL, PRIMARY KEY (id), KEY landing_page_id (landing_page_id), KEY productid (productid), CONSTRAINT landing_page_id_2 FOREIGN KEY (landing_page_id) REFERENCES kp_landing_page (landing_page_id) ON DELETE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=522630 DEFAULT CHARSET=utf8

-- kp_landing_page

kp_landing_page CREATE TABLE kp_landing_page (  landing_page_id int(11) NOT NULL AUTO_INCREMENT,  title varchar(255) COLLATE utf8mb4_bin NOT NULL,  title_multi varchar(255) COLLATE utf8mb4_bin NOT NULL,  rewrite varchar(255) COLLATE utf8mb4_bin NOT NULL,  active tinyint(4) NOT NULL DEFAULT 1,  parent int(11) NOT NULL DEFAULT 0,  ordering int(11) NOT NULL,  show_as_filter tinyint(4) NOT NULL DEFAULT 0,  popular tinyint(4) NOT NULL DEFAULT 0, color_code varchar(255) COLLATE utf8mb4_bin NOT NULL,  PRIMARY KEY (landing_page_id) ) ENGINE=InnoDB AUTO_INCREMENT=247 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

kp_landing_page_product总共包含160854行

kp_landing_page总共包含233行

使用此SELECT * FROM kp_landing_page WHERE parent = 0查询,kp_landing_page将返回9行

kp_landing_page_product使用以下命令返回大约40行

SELECT * FROM kp_landing_page lp WHERE lp.parent = '7' AND ( SELECT COUNT(*) FROM kp_landing_page_product lpp WHERE lpp.landing_page_id = lp.landing_page_id AND lpp.productid = '6176' ) != 0查询,此值可根据提供的productid进行更改

EN

Stack Overflow用户

发布于 2021-11-12 16:27:19

索引:

代码语言:javascript
复制
lp:   INDEX(landing_page_id)
lpp:  INDEX(landing_page_id, productid)  -- either order is OK

使用EXISTS (也称为"semi-join")代替

代码语言:javascript
复制
      AND (
            SELECT COUNT(*) FROM kp_landing_page_product lpp
                WHERE lpp.landing_page_id = lp.landing_page_id
                  AND lpp.productid = '6176'
        ) != 0

-->

代码语言:javascript
复制
 AND EXISTS ( SELECT 1 FROM kp_landing_page_product AS lpp
                WHERE lpp.landing_page_id = lp.landing_page_id
                  AND lpp.productid = '6176' )

当找到第一个计数时,EXISTS将停止;COUNT(*)可能需要做更多的工作才能找出确切的计数。

(如果您希望进一步讨论,请提供两个表的SHOW CREATE TABLE、每个表的大小(大约行数)和查询返回的行数。)

票数 1
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69940084

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档