使用变量时sql语句慢

And*_*man 1 mysql sql variables performance mariadb

我有以下 SQL 语句针对 MariaDB 10.1.26 运行,具有约 2.000 行并具有即时结果。

select value, datetime from Schuppen 
where (value = (select min(value) from Schuppen where (measure = 'temp') 
    and datetime between '2018-11-01 00:00:00' and '2018-11-02 00:00:00')) 
and datetime between '2018-11-01 00:00:00' and '2018-11-02 00:00:00';
Run Code Online (Sandbox Code Playgroud)

当我将以下语句与日期时间字段的变量一起使用时,执行需要大约 5.5 秒。

set @startdate = cast('2018-11-01 00:00:00' as datetime);
set @enddate = cast('2018-11-02 00:00:00' as datetime);
select value, datetime from Schuppen 
where (value = (select min(value) from Schuppen where (measure = 'temp') 
    and datetime between @startdate and @enddate)) 
and datetime between @startdate and @enddate;
Run Code Online (Sandbox Code Playgroud)

我拥有的数据行越多,执行语句所需的时间就越长。似乎变量以某种方式改变了语句的行为。

这里有什么问题?

Kai*_*aii 5

问题是查询优化器在使用变量时在寻找合适的索引方面做得不好。这是一个已知的问题。

如果您EXPLAIN在两个查询上都使用,您将看到不同之处。在不必要的时候尽量避免变量。

对于第一个查询,优化器“看到”所选值并决定可以完美地使用索引来更有效地满足所选范围。

对于第二个查询,优化器不知道定义范围的两个值,而是决定回退到 FULL SCAN。


小智 5

我使用 MySQL Workbench,@variables 对于查询/搜索给定属性的不同表非常有用。我遇到了类似的问题。在浏览不同的线程并尝试不同的事情之后,当我将 @variable 设置为与我正在搜索该变量的表中的列具有完全相同的类型相同的编码时,它运行良好。

例如:

SET @keyword = CONVERT(CAST("KEYWORD" AS CHAR(8)) USING ASCII);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我的表 customer 中的搜索列 cname 是 CHAR(8) 类型并使用 ASCII 编码:

SELECT * FROM CUSTOMERS WHERE cname=@keyword;
Run Code Online (Sandbox Code Playgroud)

如果您有多个表要查询,其中一个 cname 是 CHAR(10),另一个是 CHAR(8),那么您可以执行以下操作:

SET @keyword = "KEYWORD";
SELECT * FROM CUSTOMERS WHERE cname=CONVERT(CAST(@keyword AS CHAR(8)) USING ASCII);
SELECT * FROM EMPLOYEES WHERE cname=CONVERT(CAST(@keyword AS CHAR(10)) USING ASCII);
Run Code Online (Sandbox Code Playgroud)