Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 2个非常相似的SQL查询具有完全不同的性能_Mysql_Sql_Select_Indexing_Query Performance - Fatal编程技术网

Mysql 2个非常相似的SQL查询具有完全不同的性能

Mysql 2个非常相似的SQL查询具有完全不同的性能,mysql,sql,select,indexing,query-performance,Mysql,Sql,Select,Indexing,Query Performance,我有以下两个SQL查询,它们95%相同,但性能明显不同 SQL查询1(3s): 显示来自车辆的索引: vehicles 0 PRIMARY 1 vid A 146068 BTREE vehicles 1 new_cost_leasing 1 cid A 12 BTREE vehicles 1 new_cost_leasing 2 cost_

我有以下两个SQL查询,它们95%相同,但性能明显不同

SQL查询1(3s):

显示来自车辆的索引:

vehicles    0   PRIMARY 1   vid A   146068              BTREE           
vehicles    1   new_cost_leasing    1   cid A   12              BTREE           
vehicles    1   new_cost_leasing    2   cost_leasing    A   4564                BTREE           
vehicles    1   new_cost_leasing    3   currency    A   5216                BTREE           
vehicles    1   new_cost_leasing    4   report_month    A   24344               BTREE           
vehicles    1   new_cost_leasing    5   report_year A   29213               BTREE           
vehicles    1   new_cost_leasing    6   country A   36517               BTREE           
vehicles    1   new_cost_leasing    7   supplier    A   29213               BTREE           
vehicles    1   new_cost_leasing    8   jato_segment    A   24344               BTREE           
vehicles    1   new_cost_leasing    9   business_unit   A   36517               BTREE           
vehicles    1   new_cost_leasing    10  entity  A   73034               BTREE           
显示汇率指数:

exchange_rates  0   PRIMARY 1   fxid    A   2               BTREE           
exchange_rates  0   PRIMARY 2   currency    A   160             BTREE           
exchange_rates  0   PRIMARY 3   date    A   569250              BTREE           
exchange_rates  1   date    1   fxid    A   2               BTREE           
exchange_rates  1   date    2   date    A   28462               BTREE           
exchange_rates  1   date    3   currency    A   569250              BTREE           
exchange_rates  1   date    4   rate    A   569250              BTREE           
exchange_rates  1   fxid    1   fxid    A   2               BTREE           
exchange_rates  1   fxid    2   year    A   114             BTREE           
exchange_rates  1   fxid    3   currency    A   2904                BTREE           
exchange_rates  1   fxid    4   rate    A   569250              BTREE           
显示KPI中的索引:

kpis    0   PRIMARY 1   vid A   60308               BTREE                   
kpis    1   cost_leasing    1   cid A   2               BTREE           
kpis    1   cost_leasing    2   kid A   2               BTREE           
kpis    1   cost_leasing    3   cost_leasing    A   78              BTREE           
kpis    1   cost_leasing    4   currency    A   78              BTREE           
kpis    1   cost_leasing    5   report_month    A   1096                BTREE           
kpis    1   cost_leasing    6   report_year A   3350                BTREE           
kpis    1   cost_leasing    7   country A   1884                BTREE           
kpis    1   cost_leasing    8   supplier    A   4020                BTREE           
kpis    1   cost_leasing    9   jato_segment    A   3015                BTREE           
kpis    1   cost_leasing    10  business_unit   A   4307                BTREE           
kpis    1   cost_leasing    11  entity  A   6030                BTREE           
kpis    1   avg_cost    1   cid A   2               BTREE           
kpis    1   avg_cost    2   kid A   2               BTREE           
kpis    1   avg_cost    3   country A   48              BTREE           
kpis    1   avg_cost    4   report_year A   96              BTREE           
kpis    1   avg_cost    5   currency    A   96              BTREE           
kpis    1   avg_cost    6   cost_leasing    A   172             BTREE       
问题: 我的问题是,为什么在查询2中只有一个额外的条件(kid)(它甚至是索引的一部分)却存在如此显著的性能差异(因子30)


有人知道如何优化查询2吗?

我发现了问题:汇率列
年份
不是唯一的,车辆的选择只有
KPI选择的一半,但由于非唯一列
年份
的基数很大,
汇率
KPI
的联合创建了一个临时集合,包含200多万个条目,这对于平均操作来说是非常大的

解决方案:我没有使用
year
,而是使用了唯一的列
date
,并将条件更改为

`date` = MAKEDATE(`report_year`, 1)

这些都是不可取的:

 STR_TO_DATE(CONCAT(`report_year`, '-', `report_month`, '-01'), '%Y-%m-%d') >= '2016-01-01' 

 LAST_DAY(STR_TO_DATE(CONCAT(`report_year`, '-', `report_month`, '-01'), '%Y-%m-%d')) <= '2017-06-30'
**查询**:

set @start := '2016-04-04';
set @end := '2017-01-30';

select *, @start, @end
from table1
where (
       ((year(@start) < year(@end)) AND report_year = year(@start) and report_month >= month(@start)) 
      OR
       ((year(@start) < year(@end)) AND report_year > year(@start) and report_year < year(@end)) 
      OR
       ((year(@start) <= year(@end)) AND report_year = year(@end) and report_month <= month(@end)) 
      )  
[结果]

CREATE TABLE Table1
    (`Report_Year` int, `Report_Month` int)
;

INSERT INTO Table1
    (`Report_Year`, `Report_Month`)
VALUES
    (2015, 1), (2015, 2), (2015, 3),
    (2015, 4), (2015, 5), (2015, 6),
    (2015, 7), (2015, 8), (2015, 9),
    (2015, 10), (2015, 11), (2015, 12),
    (2016, 1), (2016, 2), (2016, 3),
    (2016, 4), (2016, 5), (2016, 6),
    (2016, 7), (2016, 8), (2016, 9),
    (2016, 10), (2016, 11), (2016, 12),
    (2017, 1), (2017, 2), (2017, 3),
    (2017, 4), (2017, 5), (2017, 6),
    (2017, 7), (2017, 8), (2017, 9),
    (2017, 10), (2017, 11), (2017, 12)
;
| Report_Year | Report_Month |     @start |       @end |
|-------------|--------------|------------|------------|
|        2016 |            4 | 2016-04-04 | 2017-01-30 |
|        2016 |            5 | 2016-04-04 | 2017-01-30 |
|        2016 |            6 | 2016-04-04 | 2017-01-30 |
|        2016 |            7 | 2016-04-04 | 2017-01-30 |
|        2016 |            8 | 2016-04-04 | 2017-01-30 |
|        2016 |            9 | 2016-04-04 | 2017-01-30 |
|        2016 |           10 | 2016-04-04 | 2017-01-30 |
|        2016 |           11 | 2016-04-04 | 2017-01-30 |
|        2016 |           12 | 2016-04-04 | 2017-01-30 |
|        2017 |            1 | 2016-04-04 | 2017-01-30 |
set @start := '2016-01-01';
set @end := '2016-06-30';

| Report_Year | Report_Month |     @start |       @end |
|-------------|--------------|------------|------------|
|        2016 |            1 | 2016-01-01 | 2016-06-30 |
|        2016 |            2 | 2016-01-01 | 2016-06-30 |
|        2016 |            3 | 2016-01-01 | 2016-06-30 |
|        2016 |            4 | 2016-01-01 | 2016-06-30 |
|        2016 |            5 | 2016-01-01 | 2016-06-30 |
|        2016 |            6 | 2016-01-01 | 2016-06-30 |

set @start := '2016-01-01';
set @end := '2017-06-30';
| Report_Year | Report_Month |     @start |       @end |
|-------------|--------------|------------|------------|
|        2016 |            1 | 2016-01-01 | 2017-06-30 |
|        2016 |            2 | 2016-01-01 | 2017-06-30 |
|        2016 |            3 | 2016-01-01 | 2017-06-30 |
|        2016 |            4 | 2016-01-01 | 2017-06-30 |
|        2016 |            5 | 2016-01-01 | 2017-06-30 |
|        2016 |            6 | 2016-01-01 | 2017-06-30 |
|        2016 |            7 | 2016-01-01 | 2017-06-30 |
|        2016 |            8 | 2016-01-01 | 2017-06-30 |
|        2016 |            9 | 2016-01-01 | 2017-06-30 |
|        2016 |           10 | 2016-01-01 | 2017-06-30 |
|        2016 |           11 | 2016-01-01 | 2017-06-30 |
|        2016 |           12 | 2016-01-01 | 2017-06-30 |
|        2017 |            1 | 2016-01-01 | 2017-06-30 |
|        2017 |            2 | 2016-01-01 | 2017-06-30 |
|        2017 |            3 | 2016-01-01 | 2017-06-30 |
|        2017 |            4 | 2016-01-01 | 2017-06-30 |
|        2017 |            5 | 2016-01-01 | 2017-06-30 |
|        2017 |            6 | 2016-01-01 | 2017-06-30 |
[结果]

CREATE TABLE Table1
    (`Report_Year` int, `Report_Month` int)
;

INSERT INTO Table1
    (`Report_Year`, `Report_Month`)
VALUES
    (2015, 1), (2015, 2), (2015, 3),
    (2015, 4), (2015, 5), (2015, 6),
    (2015, 7), (2015, 8), (2015, 9),
    (2015, 10), (2015, 11), (2015, 12),
    (2016, 1), (2016, 2), (2016, 3),
    (2016, 4), (2016, 5), (2016, 6),
    (2016, 7), (2016, 8), (2016, 9),
    (2016, 10), (2016, 11), (2016, 12),
    (2017, 1), (2017, 2), (2017, 3),
    (2017, 4), (2017, 5), (2017, 6),
    (2017, 7), (2017, 8), (2017, 9),
    (2017, 10), (2017, 11), (2017, 12)
;
| Report_Year | Report_Month |     @start |       @end |
|-------------|--------------|------------|------------|
|        2016 |            4 | 2016-04-04 | 2017-01-30 |
|        2016 |            5 | 2016-04-04 | 2017-01-30 |
|        2016 |            6 | 2016-04-04 | 2017-01-30 |
|        2016 |            7 | 2016-04-04 | 2017-01-30 |
|        2016 |            8 | 2016-04-04 | 2017-01-30 |
|        2016 |            9 | 2016-04-04 | 2017-01-30 |
|        2016 |           10 | 2016-04-04 | 2017-01-30 |
|        2016 |           11 | 2016-04-04 | 2017-01-30 |
|        2016 |           12 | 2016-04-04 | 2017-01-30 |
|        2017 |            1 | 2016-04-04 | 2017-01-30 |
set @start := '2016-01-01';
set @end := '2016-06-30';

| Report_Year | Report_Month |     @start |       @end |
|-------------|--------------|------------|------------|
|        2016 |            1 | 2016-01-01 | 2016-06-30 |
|        2016 |            2 | 2016-01-01 | 2016-06-30 |
|        2016 |            3 | 2016-01-01 | 2016-06-30 |
|        2016 |            4 | 2016-01-01 | 2016-06-30 |
|        2016 |            5 | 2016-01-01 | 2016-06-30 |
|        2016 |            6 | 2016-01-01 | 2016-06-30 |

set @start := '2016-01-01';
set @end := '2017-06-30';
| Report_Year | Report_Month |     @start |       @end |
|-------------|--------------|------------|------------|
|        2016 |            1 | 2016-01-01 | 2017-06-30 |
|        2016 |            2 | 2016-01-01 | 2017-06-30 |
|        2016 |            3 | 2016-01-01 | 2017-06-30 |
|        2016 |            4 | 2016-01-01 | 2017-06-30 |
|        2016 |            5 | 2016-01-01 | 2017-06-30 |
|        2016 |            6 | 2016-01-01 | 2017-06-30 |
|        2016 |            7 | 2016-01-01 | 2017-06-30 |
|        2016 |            8 | 2016-01-01 | 2017-06-30 |
|        2016 |            9 | 2016-01-01 | 2017-06-30 |
|        2016 |           10 | 2016-01-01 | 2017-06-30 |
|        2016 |           11 | 2016-01-01 | 2017-06-30 |
|        2016 |           12 | 2016-01-01 | 2017-06-30 |
|        2017 |            1 | 2016-01-01 | 2017-06-30 |
|        2017 |            2 | 2016-01-01 | 2017-06-30 |
|        2017 |            3 | 2016-01-01 | 2017-06-30 |
|        2017 |            4 | 2016-01-01 | 2017-06-30 |
|        2017 |            5 | 2016-01-01 | 2017-06-30 |
|        2017 |            6 | 2016-01-01 | 2017-06-30 |

萨尔盖博是一个优势。更好地处理日期是一个要点。这里还有一些要点

11列索引几乎肯定是一种浪费。即使是6列索引也不太可能得到充分利用。将仅使用索引中最左边的列。通常它会到达下一列不可用的点,因此它会停止

一般来说,将日期分为年、月和日不是一个好主意。由于您似乎只需要年份和月份,建议使用
CHAR(7)CHARSET ascii
值,如“2017-06”。或者你真的有报告在一个月内停止?

请用所涉及的表限定每个列名。非常重要的是,我们知道哪个表,例如,
fxid

请使用
JOIN。。关于
语法:

FROM vehicles AS a
JOIN exchange_rates AS b  ON a.currency = b.currency
(我更喜欢
作为v
作为er
作为助记符。)

所需索引(包含当前年份/生产任务列):


关于创建索引的更多信息:

如果它们使用完全不同的表,我不会说它们95%相同。具有可能不同的结构、索引和记录数。。。需要更多信息。除了KPI额外包含字段
kid
之外,选项卡是相同的。索引相同,除了kpi索引额外包含
kid
as列之外,它们是相等的。您可以在解释答案中看到受影响的行。您可以发布您的索引定义吗?请阅读此内容,并特别注意有关查询性能的部分。请回答您的问题以提供更多信息。您的一个索引可能缺少一列,但我们无法确定是哪一列。我添加了相关的KPI索引。感谢您为“sargable谓词”提供的示例。再次感谢您,在sqlfiddle.com的查询中缺少分号。分号在sqlfiddle处退出,但在选择标记布局时被删除。。。布局中可能存在sqlfiddle错误。顺便说一句,如果更改数据模型是一个选项,我建议使用日期字段,而不是年份和月份列。如果您知道在一个SELECT中使用的全局行数超过一百万,则没有意义,您的my.cnf/ini中的这一行--sql_select_limit=1M#用于停止错误的数据量--将在您任职期间或在有人为您的my.cfg删除它之前对您有效。
b,d: INDEX(fxid, currency, year)
a: INDEX(cid, currency, report_year)
c: INDEX(kid, cid, currency, report_year)