前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >还在手工优化慢SQL? 小米出品SQL优化神器

还在手工优化慢SQL? 小米出品SQL优化神器

原创
作者头像
code-x
修改2022-08-17 15:02:57
1.4K1
修改2022-08-17 15:02:57
举报
文章被收录于专栏:code-x

容我标题党一回

介绍

soar是由小米开源的SQL优化器和重写器

项目地址 github.com/XiaoMi/soar

目前是仅支持mysql

使用

  • 基于 ubuntu20.04 lts

按文档安装后

github.com/XiaoMi/soar…

现有 categorygoods 表; 除主键外, 没有任何索引

写一段垃圾sql

代码语言:javascript
复制
SELECT  
  * 
FROM  
  (
SELECT  
  g.NAME, c.NAME  AS  cats  
FROM  
  goods  g  
  LEFT JOIN  category  c  ON  g. cats_id  = c. id
) g  
WHERE  
  g.NAME  = '充电器'

在soar可执行文件的目录定义配置文件soar.yaml

代码语言:javascript
复制
test-dsn:
    addr:     192.168.101.128:3307
    schema:   localdb
    user:     root
    password: "123456"
    disable:  false
# 是否允许测试环境与线上环境配置相同
allow-online-as-test: true
# 是否清理测试时产生的临时文件
drop-test-temporary: true
# 语法检查小工具
only-syntax-check: false
sampling-statistic-target: 100
sampling: true
# 日志级别,[0:Emergency, 1:Alert, 2:Critical, 3:Error, 4:Warning, 5:Notice, 6:Informational, 7:Debug]
log-level: 7
log-output: ./soar.log
# 优化建议输出格式
report-type: markdown		#可以为markdown和html
ignore-rules:
- ""
# 黑名单中的 SQL 将不会给评审意见。一行一条 SQL,可以是正则也可以是指纹,填写指纹时注意问号需要加反斜线转义。
blacklist: ${your_config_dir}/soar.blacklist
# 启发式算法相关配置
max-join-table-count: 5
max-group-by-cols-count: 5
max-distinct-count: 5
max-index-cols-count: 5
max-total-rows: 9999999
spaghetti-query-length: 2048
allow-drop-index: false
# EXPLAIN相关配置
explain-sql-report-type: pretty
explain-type: extended
explain-format: traditional
explain-warn-select-type:
- ""
explain-warn-access-type:
- ALL
explain-max-keys: 3
explain-min-keys: 0
explain-max-rows: 10000
explain-warn-extra:
- ""
explain-max-filtered: 100
explain-warn-scalability:
- O(n)
query: ""
list-heuristic-rules: false
list-test-sqls: false
verbose: true

然后命令行启动

代码语言:javascript
复制
echo "SELECT * FROM (SELECT g.NAME, c.NAME AS cats FROM goods g LEFT JOIN category c ON g.cats_id = c.id ) g WHERE g.NAME = '充电器';" | ./soar  -report-type markdown > result.md

结果以markdown格式输出

以下是result.md文件内容

Query: D4968C97EF14B742

☆ ☆ ☆ ☆ ☆ 15分

代码语言:javascript
复制
SELECT  
  * 
FROM  
  (
SELECT  
  g. NAME, c. NAME  AS  cats  
FROM  
  goods  g  
  LEFT JOIN  category  c  ON  g. cats_id  = c. id
) g  
WHERE  
  g. NAME  = '充电器'

Explain信息

id

select_type

table

partitions

type

possible_keys

key

key_len

ref

rows

filtered

scalability

Extra

1

SIMPLE

g

NULL

ALL

NULL

1

☠️ 100.00%

☠️ O(n)

Using where

1

SIMPLE

c

NULL

eq_ref

PRIMARY

PRIMARY

4

localdb.g.cats_id

1

☠️ 100.00%

☠️ O(n)

Using where

Explain信息解读

SelectType信息解读
  • SIMPLE: 简单SELECT(不使用UNION或子查询等).
Type信息解读
  • ☠️ ALL: 最坏的情况, 从头到尾全表扫描.
  • eq_ref: 除const类型外最好的可能实现的连接类型. 它用在一个索引的所有部分被连接使用并且索引是UNIQUE或PRIMARY KEY, 对于每个索引键, 表中只有一条记录与之匹配. 例:'SELECT * FROM ref_table,tbl WHERE ref_table.key_column=tbl.column;'.
Extra信息解读
  • Using where: WHERE条件用于筛选出与下一个表匹配的数据然后返回给客户端. 除非故意做的全表扫描, 否则连接类型是ALL或者是index, 且在Extra列的值中没有Using Where, 则该查询可能是有问题的.

为localdb库的goods表添加索引

  • Item: IDX.001
  • Severity: L2
  • Content: 为列cats_id添加索引,散粒度为: 100.00%;
  • Case: ALTER TABLE `localdb`.`goods` add index `idx_cats_id` (`cats_id`) ;

为localdb库的category表添加索引

  • Item: IDX.002
  • Severity: L2
  • Content: 为列NAME添加索引,散粒度为: 100.00%;
  • Case: ALTER TABLE `localdb`.`category` add index `idx_NAME` (`NAME`(191)) ;

建议使用AS关键字显示声明一个别名

  • Item: ALI.001
  • Severity: L0
  • Content: 在列或表别名(如"tbl AS alias")中, 明确使用AS关键字比隐含别名(如"tbl alias")更易懂。

参数比较包含隐式转换,无法使用索引

  • Item: ARG.003
  • Severity: L4
  • Content: `goods`.`cats_id` (int) VS `category`.`id` (int unsigned) datatype not match

最外层SELECT未指定WHERE条件

  • Item: CLA.001
  • Severity: L4
  • Content: SELECT语句没有WHERE子句,可能检查比预期更多的行(全表扫描)。对于SELECT COUNT(*)类型的请求如果不要求精度,建议使用SHOW TABLE STATUS或EXPLAIN替代。

不建议使用SELECT * 类型查询

  • Item: COL.001
  • Severity: L1
  • Content: 当表结构变更时,使用*通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。

MySQL对子查询的优化效果不佳

  • Item: SUB.001
  • Severity: L4
  • Content: MySQL将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为JOIN或LEFT OUTER JOIN。

看起来还是很强大的, 尤其是对于经验不足的同学

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 使用
  • Query: D4968C97EF14B742
    • Explain信息
      • Explain信息解读
    • 为localdb库的goods表添加索引
      • 为localdb库的category表添加索引
        • 建议使用AS关键字显示声明一个别名
          • 参数比较包含隐式转换,无法使用索引
            • 最外层SELECT未指定WHERE条件
              • 不建议使用SELECT * 类型查询
                • MySQL对子查询的优化效果不佳
                相关产品与服务
                云数据库 SQL Server
                腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档