优化 MySQL 查询以获取页面的正确模板

Posted

技术标签:

【中文标题】优化 MySQL 查询以获取页面的正确模板【英文标题】:Optimizing MySQL query to get the right template for a page 【发布时间】:2014-09-30 07:17:12 【问题描述】:

下面的 mysql 查询是这样工作的: 在类似树视图的结构中,它正在搜索要使用的模板。

例如:

首页 (tpl: home) - (lvl: pagId) Carrousel (tpl: carrousel) - (lvl: subId) Carrousel 项目 1(tpl:inherit from parent)-(lvl:sub2Id) 联系人(tpl:联系人)-(lvl:pagId) 地址 (tpl: inherit from parent) - (lvl: subId) 论坛(tpl:论坛)-(lvl:pagId) 主题(tpl:论坛)-(lvl:subId) 消息(tpl:论坛)-(lvl:subId) 常见问题 (tpl: 常见问题) - (lvl: pagId) 问题 1 (tpl: question) - (lvl: subId) 问题 2 (tpl: question) - (lvl: subId) 子问题 1 (tpl: inherit from parent) - (lvl: sub2Id) 子问题 2 (tpl: subquestion) - (lvl: sub2Id)

当一个孩子没有 templateId 时,它继承了他父母的模板。 但是当一个孩子有一个 templateId 时,它会保留他自己的模板。

问题是以下查询的持续时间约为 1 秒,并且是 API 中经常使用的查询。如何在不丢失工作的情况下优化下面的查询?还是拆分查询会更好?

SELECT 
                        `c`.*, 
                        `c`.`pagId` AS `parentPagId`,
                        `c`.`subId` AS `parentSubId`,
                        `c`.`sub2Id` AS `parentSub2Id`,
                        `c`.`sub3Id` AS `parentSub3Id`,
                        IF( 
                            `template`.`templateName` IS NOT NULL,
                            `template`.`templateName`,
                            (
                                SELECT 
                                    IF(
                                        `template`.`templateName` IS NOT NULL,
                                        `template`.`templateName`,
                                        'default'
                                    )
                                FROM
                                    `content`
                                LEFT JOIN
                                    `template`
                                ON
                                    `content`.`templateId` = `template`.`id`
                                WHERE
                                    CASE WHEN 
                                        ( `content`.`sub3Id` = '' AND `content`.`sub2Id` != '' AND `content`.`templateId` != 0 AND `content`.`templateId` IS NOT NULL )
                                    THEN 
                                         `content`.`sub2Id` = `c`.`sub2Id`
                                    WHEN 
                                        ( `content`.`sub2Id` = '' AND `content`.`subId` != '' AND `content`.`templateId` != 0 AND `content`.`templateId` IS NOT NULL )
                                    THEN 
                                        `content`.`subId` = `c`.`subId`
                                    WHEN 
                                        ( `content`.`subId` = '' AND `content`.`pagId` != '' AND `content`.`templateId` != 0 AND `content`.`templateId` IS NOT NULL)
                                    THEN 
                                        `content`.`pagId` = `c`.`pagId`
                                    ELSE
                                        ''
                                    END
                                AND
                                    `content`.`siteId` = '1' 
                                AND
                                    `content`.`langId` = '1'
                                AND
                                    `content`.`active` = 1
                                LIMIT 1
                            )
                        ) AS `template`
                    FROM 
                        `content` `c`
                    LEFT JOIN 
                        `template` 
                        ON `c`.`templateId` = `template`.`id`
                    WHERE 
                        `c`.`siteId` = '1' 
                    AND 
                        `c`.`langId` = '1'
                    AND
                        `c`.`active` = 1
                    ORDER BY 
                        `c`.`order`, 
                        `c`.`pagId`, 
                        `c`.`subId`, 
                        `c`.`sub2Id`, 
                        `c`.`sub3Id`

更新 我有 2 张桌子:

表 1(“内容”)字段:

页面标识 子标识 sub2Id sub3Id 内容 模板标识

表 2(“模板”)字段:

身份证 模板名称

我想要做什么(以及什么在起作用,但在此查询中花费了太多时间):

    从数据库中获取所有页面 如果 content.templateId > 0:从具有 template.id = content.templateId 的行中获取 templateName 如果 content.templateId = 0 或 NULL:获取父模板 -> 这就是子查询的作用... 如果模板没有生成有效的模板名称:模板 =“默认”

【问题讨论】:

【参考方案1】:

您在这里创建了一个非常复杂的 SQL 命令。这没有多大意义。当然,您的问题中缺少表定义也无济于事。我们应该猜到吗?

我很困惑,你有template.templateNametemplate.id,有时你使用一个,然后另一个?拥有id 时,请始终使用它。它应该是唯一的索引号,而名称可以是任何东西,甚至可能不是唯一的或索引的。

我很清楚你试图在一个查询中做太多事情。退后一步,用简单的步骤写下你想做什么。

    您似乎对每个页面的内容都有一个“内容”表。如果它引用了一个模板,你就完成了,得到它。

    如果它不引用模板,请向父级询问它的模板。

应该就这么简单。您可能应该在 php 中执行此操作,并且仅在需要时向数据库询问信息。您将得到一个简单的查询:

SELECT * 
FROM content 
WHERE siteId = 1 AND langId = 1 AND active = 1 AND pagId = ?

请注意,我只要求我感兴趣的页面。我可能弄错了,但您似乎要求数据库中的所有页面。你可能只需要一个。

【讨论】:

以上是关于优化 MySQL 查询以获取页面的正确模板的主要内容,如果未能解决你的问题,请参考以下文章

MySQL-性能优化

MySQL-性能优化

优化 SQL 查询以从大量 MySQL 数据库中获取数据

MySQL 查询优化以获得月度报告

用于获取地理位置记录的 MySQL 查询优化

需要帮助优化 mysql 查询以使其按索引快速排序