Mysql 查询与 order by。奇怪的执行计划

Posted

技术标签:

【中文标题】Mysql 查询与 order by。奇怪的执行计划【英文标题】:Mysql query with order by. Strange execution plan 【发布时间】:2016-01-02 23:27:46 【问题描述】:

我有 3 张桌子:

Product (about 700000 rows)
ProductId int(11) AI PK 
ManufacturerId int(11) FK
Name varchar(256) 
Description text 
SKU varchar(64) 
Code varchar(64) 
ArtId int(11) 
StockStateId int(2) FK
Quantity int(11) 
QuantityText varchar(61) 
Price decimal(12,2) 
CurrencyId int(2) 
AutoImport bit(1) 
ImpactOnBalance bit(1) 
HasPhoto bit(1) 
HasParams bit(1)

StockState (3 rows)
StockStateId int(2) AI PK 
Name varchar(64)

Manufacturer (about 200 rows)
ManufacturerId int(11) AI PK 
Name varchar(64) 
Description text 
SortOrder int(11)

这是我的查询

select
     p.ProductId
    ,p.Name
    ,p.Quantity
    ,p.QuantityText
    ,m.ManufacturerId
    ,m.Name as ManufacturerName
    ,ss.StockStateId
    ,ss.Name as StockStateName
from Product p
inner join Manufacturer m on m.ManufacturerId = p.ManufacturerId
inner join StockState ss on ss.StockStateId = p.StockStateId
order by p.ProductId asc
limit 1000, 25

我不明白为什么 mysql 不使用正确的索引(大约需要 10 秒才能得到结果)。执行计划长这样 first query。 我可以强制mysql使用主索引

from Product p force index (primary)

它将性能提高到 0.015 秒,但我将在 SP 中使用此查询,其中顺序取决于输入参数。所以我添加了虚拟案例条件

set @order = '';
select
     p.ProductId
    ,p.Name
    ,p.Quantity
    ,p.QuantityText
    ,m.ManufacturerId
    ,m.Name as ManufacturerName
    ,ss.StockStateId
    ,ss.Name as StockStateName
    from Product p force index (primary)
inner join Manufacturer m on m.ManufacturerId = p.ManufacturerId
inner join StockState ss on ss.StockStateId = p.StockStateId
order by case when @order = '' then p.ProductId end asc
limit 1000, 25

这个查询应该有与前一个相同的执行计划(按相同的列排序,即 PK),但不,我有文件排序。 third query

这是为什么?有人可以帮我解决这个问题吗? (提高查询性能)r

【问题讨论】:

【参考方案1】:

我觉得你应该试试这个,有左连接的概念等等。

set @order = '';
select
     p.ProductId
    ,p.Name
    ,p.Quantity
    ,p.QuantityText
    ,m.ManufacturerId
    ,m.Name as ManufacturerName
    ,ss.StockStateId
    ,ss.Name as StockStateName
    from Product p force index (primary)
//this line what I mean 
inner join Manufacturer m on p.ManufacturerId = m.ManufacturerId
//also this line what I mean
inner join StockState ss on p.StockStateId = ss.StockStateId
order by case when @order = '' then p.ProductId end asc
limit 1000, 25

因为你必须先检查你的产品中的行,然后加入制造商

如果你先检查制造商,如果制造商中的行在产品中不存在就会出现问题(浪费时间)

【讨论】:

以上是关于Mysql 查询与 order by。奇怪的执行计划的主要内容,如果未能解决你的问题,请参考以下文章

Mysql5.7中子查询时order by与group by合用无效的解决办法

php 数据库查询order by 与查询返回的数据类型

坑,MySQL中 order by 与 limit 混用,分页有BUG!

MySQL 查询优化与 group by 和 order by rand

如果使用 ORDER BY String Column,MySQL 查询需要很长时间才能执行

Mysql ORDER BY 或 MAX() 用于几个表字段排序?