SQL面试题:一个优化案例

这篇具有很好参考价值的文章主要介绍了SQL面试题:一个优化案例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题描述

假如存在以下两个表:

CREATE TABLE `customer` (
`C_CUSTKEY` int NOT NULL,
`C_NAME` varchar(25) NOT NULL,
`C_ADDRESS` varchar(40) NOT NULL,
`C_NATIONKEY` int NOT NULL,
`C_PHONE` char(15) NOT NULL,
`C_ACCTBAL` decimal(15,2) NOT NULL,
`C_MKTSEGMENT` char(10) NOT NULL,
`C_COMMENT` varchar(117) NOT NULL,
 PRIMARY KEY (`C_CUSTKEY`)
) ENGINE=InnoDB;

  -- tpch.orders definition
CREATE TABLE `orders` (
`O_ORDERKEY` int NOT NULL,
`O_CUSTKEY` int NOT NULL,
`O_ORDERSTATUS` char(1) NOT NULL,
`O_TOTALPRICE` decimal(15,2) NOT NULL,
`O_ORDERDATE` date NOT NULL,
`O_ORDERPRIORITY` char(15) NOT NULL,
`O_CLERK` char(15) NOT NULL,
`O_SHIPPRIORITY` int NOT NULL,
`O_COMMENT` varchar(79) NOT NULL,
PRIMARY KEY (`O_ORDERKEY`)
) ENGINE=InnoDB;

请问,下面的查询语句应该如何优化?

select * 
from customer 
where c_custkey = (select max(o_custkey) 
                   from orders 
                   where subdate(o_orderdate, interval '1' DAY) < '2022-12-20');

思路分析

首先,customer 表的 c_custkey 字段是主键,查询条件是等值查找,已经最优了。

其次,子查询的条件字段没有索引,需要全表扫描。看一下执行计划:

EXPLAIN
select * from customer 
where c_custkey = (select max(o_custkey) 
from orders where subdate(o_orderdate, interval '1' DAY) < '2022-12-20');

id|select_type|table |partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra                         |
--+-----------+------+----------+----+-------------+---+-------+---+----+--------+------------------------------+
 1|PRIMARY    |      |          |    |             |   |       |   |    |        |no matching row in const table|
 2|SUBQUERY   |orders|          |ALL |             |   |       |   |   1|   100.0|Using where                   |

因此主要优化这个子查询。

第一步,考虑子查询使用 o_orderdate 作为条件,可以基于这个字段创建索引,同时需要把 subdate 函数放到表达式右边,否则会导致索引失效。

CREATE INDEX idx_orders_date ON orders(o_orderdate);

EXPLAIN
select * from customer 
where c_custkey = (select max(o_custkey) 
from orders where o_orderdate < adddate('2022-12-20', interval '1' DAY));

id|select_type|table |partitions|type |possible_keys  |key            |key_len|ref|rows|filtered|Extra                         |
--+-----------+------+----------+-----+---------------+---------------+-------+---+----+--------+------------------------------+
 1|PRIMARY    |      |          |     |               |               |       |   |    |        |no matching row in const table|
 2|SUBQUERY   |orders|          |range|idx_orders_date|idx_orders_date|3      |   |   1|   100.0|Using index condition         |

对于 orders 表的访问类型变成了索引范围扫描(range),但是仍然不够理想,因为扫描完索引之后还需要回表查询 max(o_custkey)。

第二步,考虑利用覆盖索引优化,避免回表。可以基于 o_orderdate 和 o_custkey 创建一个复合索引。

CREATE INDEX idx_orders_date_cust ON orders(o_orderdate, o_custkey);

EXPLAIN
select * from customer 
where c_custkey = (select max(o_custkey) 
from orders where o_orderdate < adddate('2022-12-20', interval '1' DAY));

id|select_type|table |partitions|type |possible_keys                       |key                 |key_len|ref|rows|filtered|Extra                         |
--+-----------+------+----------+-----+------------------------------------+--------------------+-------+---+----+--------+------------------------------+
 1|PRIMARY    |      |          |     |                                    |                    |       |   |    |        |no matching row in const table|
 2|SUBQUERY   |orders|          |index|idx_orders_date,idx_orders_date_cust|idx_orders_date_cust|7      |   |   1|   100.0|Using where; Using index      |

第三步,考虑复合索引的字段顺序是否有更好的选择,也就是说 (o_orderdate, o_custkey) 还是 (o_custkey, o_orderdate)。

如果选择 (o_orderdate, o_custkey),通过覆盖索引获取数据时,需要找出 o_orderdate 小于 2022-12-21 的所有索引节点,然后遍历其中的 o_custkey,找出最大的值。

如果选择 (o_custkey, o_orderdate),通过覆盖索引获取数据时,需要按照 o_custkey 从大到小查找索引,找出其中 o_orderdate 小于 2022-12-21 的第一个索引节点即可。

MySQL 优化器目前不支持第二种选择。文章来源地址https://www.toymoban.com/news/detail-623009.html

到了这里,关于SQL面试题:一个优化案例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL数据库的性能优化----(一步一个脚印)

    一、MySQL数据库的优化目标、基本原则: 1、优化目标: MySQL数据库是常见的两个瓶颈是CPU和I/O的瓶颈,无论是索引优化、还是表结构优化,参数优化,最后都可以归纳到这这两个分类中: (1)减少 I/O 次数: I/O是数据库最容易瓶颈的地方,大部分数据库操作中超过90%的时间

    2024年02月03日
    浏览(90)
  • SQL面试题:一个优化案例

    假如存在以下两个表: 请问,下面的查询语句应该如何优化? 首先,customer 表的 c_custkey 字段是主键,查询条件是等值查找,已经最优了。 其次,子查询的条件字段没有索引,需要全表扫描。看一下执行计划: 因此主要优化这个子查询。 第一步 ,考虑子查询使用 o_orderda

    2024年02月14日
    浏览(23)
  • 从小白到数据库达人!Mysql优化让你的社招面试无往不利!

    大家好,我是小米,在这个美好的时刻又迎来了我们的技术小窝。今天,我们要聊一聊一个在数据库领域中无比重要的话题 —— Mysql 优化 !是不是感觉很兴奋呢?废话不多说,让我们直接进入今天的主题。 首先,我们要了解一下 Mysql 到底是什么。 Mysql 是一个开源的关系型

    2024年02月14日
    浏览(34)
  • SQL数据库案例1——创建商店数据库

    创建商店数据库Commodities_Management 创建商品表、供应商表、进货表、销售表 各表分别输入数据 库名:Commodities_Management 字符集:utf16 表一:商品表 字段名 类型 长度 约束 商品编号 varchar 10 外键(参照进货表) 商品名 varchar 30 — 规格 varchar 20 — 供应商编号 varchar 10 非空 表二:

    2024年02月12日
    浏览(48)
  • smartsofthelp 5.0 最专业的数据库优化工具,数据库配置优化,数据库高并发优化,SQL 语句优化...

      下载地址:百度网盘 请输入提取码 SQL操作返回历史记录: 2023-08-21 20:42:08:220  输入:select @@version as 版本号 2023-08-21 20:42:08:223  输出:当前数据库实例版本号:Microsoft SQL Server 2012 - 11.0.2100.60 (X64)      Feb 10 2012 19:39:15      Copyright (c) Microsoft Corporation     Developer Edition (

    2024年02月12日
    浏览(59)
  • 关于数据库SQL优化

      在项目上线初期,业务数据量相对较少,SQL的执行效率对程序运行效率的影响可能不太明显,因此开发和运维人员可能无法判断SQL对程序的运行效率有多大。但随着时间的积累,业务数据量的增多,SQL的执行效率对程序的运行效率的影响逐渐增大,此时对SQL的优化就很有必

    2024年02月08日
    浏览(63)
  • SQL笔记 -- 数据库结构优化

    不常用的数据为冷数据,反之则为热数据。如果一个表中的数据存在明显的使用频率差异,那么可以将冷热数据分离。通过这种分解可以提高表的查询效率。对于字段很多且有些字段使用不频繁的表,可以通过这种分解的方式来优化数据库的性能。 例如: 会员members表存储会

    2024年01月22日
    浏览(59)
  • 数据库优化案例—某市中心医院HIS系统

    记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的。这也是为什么自己特别喜欢看案例,今天也开始分享自己做的优化案例。 最近一直很忙,博客产出也少的可怜,今天整理了一下自己做过优化或各种方案的

    2024年02月05日
    浏览(48)
  • SQL Server 数据库优化分享

           随着数据量和业务复杂性的增加,数据库优化变得越来越重要。通过对 SQL Server 数据库进行优化,您可以提高查询性能、减少资源消耗,从而改善整体系统性能。以下是一些优化技巧,可帮助您实现更高效、更可靠的数据库操作。 使用恰当的索引: 索引是一种提供快

    2024年02月11日
    浏览(55)
  • 数据库优化:探索 SQL 中的索引

    推荐:使用 NSDT场景编辑器 助你快速搭建可编辑的3D应用场景 在一本书中搜索特定主题时,我们将首先访问索引页面(该页面位于该书的开头),并找到包含我们感兴趣的主题的页码。现在,想象一下在没有索引页的书中找到特定主题是多么不方便。为此,我们必须搜索书中

    2024年02月14日
    浏览(72)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包