Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/71.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如何选择列。。?_Mysql_Sql - Fatal编程技术网

MySQL如何选择列。。?

MySQL如何选择列。。?,mysql,sql,Mysql,Sql,当MySQL查询的select语句中存在多个相同的表达式时,服务器是再次计算该表达式还是重用它 示例: 从表中选择列1,upper(Column1)作为名称1,其中upper(Column1)类似“ADAM%” 在上面的查询中,upper(Column1)表达式是否计算了一次或两次 另外,你能告诉我在哪里可以找到更多关于这个的信息吗 TIA在本查询中: Select Column1, upper(Column1) as name1 from Table where upper(Column1)

当MySQL查询的select语句中存在多个相同的表达式时,服务器是再次计算该表达式还是重用它

示例:

从表中选择列1,upper(Column1)作为名称1,其中upper(Column1)类似“ADAM%”

在上面的查询中,upper(Column1)表达式是否计算了一次或两次

另外,你能告诉我在哪里可以找到更多关于这个的信息吗

TIA在本查询中:

Select Column1, upper(Column1) as name1
from Table
where upper(Column1) like 'ADAM%';
我猜
上部(第1列)
会被计算两次。一些数据库有复杂的优化,可以找到常见的子表达式;我认为MySQL没有

但是,这没有什么区别<与读取数据和类似的
相比,code>upper()
应该相对便宜。这一点尤其正确,因为查询不能使用索引,所以必须进行完整的表扫描

MySQL确实为您提供了解决此问题的方法。如果您使用的
具有
,则应仅执行一次计算:

Select Column1, upper(Column1) as name1
from Table
having upper(Column1) like 'ADAM%';

这是一个MySQL扩展。

从逻辑上讲,FROM和WHERE子句是在SELECT子句之前计算的,一些数据库(我知道的Oracle、SQL Server)可以将谓词别名分配给计算值(甚至是大小写表达式),这些值可以稍后在解释/执行计划中重用。MySQL解释计划没有透露我所知道的信息级别,因此我无法确定MySQL是否能够做到这一点

另一个例子是一些“复杂”的东西,例如在GROUP BY和SELECT子句中重复的大写或大小写表达式,正是SELECT子句从中受益,因为GROUP BY的执行时间早于SELECT。(这可能就是早期提出的“把戏”条款起作用的原因。)


因此,我认为了解从句的逻辑顺序对判断这一点非常有用。e、 g.虽然我不能肯定地回答你的具体问题。

我有几点要回答这个问题

无优化 回答你的问题:不,我从来没有读过任何MySQL“记得”它已经在WHERE子句中计算过函数的报告。它分别计算WHERE子句和select列表

另一方面,MySQL将对确定性常量函数(即对每一行计算为相同常量值的表达式)进行一次计算,这是一种更普遍有用的性能改进。看

不要微优化
UPPER()
并不昂贵。即使运行这个函数100万次,仍然只需要0.04秒,这比计算字符串文字所需的时间还要多,但仍然不太明显

mysql> select benchmark(1000000, 'adam');
+----------------------------+
| benchmark(1000000, 'adam') |
+----------------------------+
|                          0 |
+----------------------------+
1 row in set (0.01 sec)

mysql> select benchmark(1000000, upper('adam'));
+-----------------------------------+
| benchmark(1000000, upper('adam')) |
+-----------------------------------+
|                                 0 |
+-----------------------------------+
1 row in set (0.04 sec)
不区分大小写的搜索 如果使用不区分大小写的排序规则(这是默认设置),则在显示的查询中根本不必使用
UPPER()

由于“ci”排序规则,默认情况下,
LIKE
谓词进行不区分大小写的比较

mysql> show variables like '%collation%';
+----------------------+--------------------+
| Variable_name        | Value              |
+----------------------+--------------------+
| collation_connection | utf8mb4_0900_ai_ci |
| collation_database   | utf8_general_ci    |
| collation_server     | utf8_general_ci    |
+----------------------+--------------------+

mysql> select 'abc' like 'ABC';
+------------------+
| 'abc' like 'ABC' |
+------------------+
|                1 |
+------------------+
撒娇 在WHERE子句中的表达式比较中计算
UPPER()
,对性能的影响要大得多

假设您的表有100万行,但其中只有1000行符合您要查找的“ADAM%”模式。使用类似以下内容的WHERE子句:

mysql> EXPLAIN SELECT UPPER(column1) AS name1 FROM MyTable
       WHERE UPPER(column1) LIKE 'ADAM%'\G

           id: 1
  select_type: SIMPLE
        table: MyTable
   partitions: NULL
         type: index
possible_keys: NULL
          key: column1
      key_len: 153
          ref: NULL
         rows: 735250    <-- this is an order-of-magnitude estimate
     filtered: 100.00
        Extra: Using where; Using index

然后,当您引用新列时,它可能会使用索引。但是,您不使用定义列的表达式,只使用列名称bare,就像sargability的常规规则一样。

您是否检查了解释计划?请回滚上次编辑(我无法在手机上执行)。编辑会丢失OP的某些特定性。OP不是在SELECT子句中讨论相同的列。OP的问题是关于两个
upper()
调用。在这样的WHERE子句中使用表达式会使查询无法使用索引进行优化,因此在select列表中进行额外计算的成本是您最不担心的@如果我没有错的话,BillKarwin MySQL 5.7提供了表达式(虚拟列)索引和Postgres。看看他们。如果可能的话,帮我回答这个问题。谢谢。MySQL确实为您提供了解决这一问题的方法。如果您使用have我在哪里可以找到此..的文档。。?请帮帮我。谢谢
mysql> EXPLAIN SELECT UPPER(column1) AS name1 FROM MyTable
       WHERE column1 LIKE 'ADAM%'\G

           id: 1
  select_type: SIMPLE
        table: MyTable
   partitions: NULL
         type: range
possible_keys: column1
          key: column1
      key_len: 153
          ref: NULL
         rows: 1000    <-- much better!
     filtered: 100.00
        Extra: Using where; Using index
mysql> ALTER TABLE MyTable 
       ADD COLUMN column1_upper VARCHAR(50) AS (UPPER(column1)),
       ADD KEY (column1_upper);