23.MySQL优化Row Constructor Expression Optimization

介绍

行构造函数允许同时比较多个值。举例来说,这两个语句在语义上是等价的:

SELECT * FROM t1 WHERE (column1,column2) = (1,1);
SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;

同时,优化器采用相同的方式处理两个SQL语句。

如果行构造函数列未覆盖索引的前缀,则优化程序不太可能使用可用索引。思考下面这张表,这张表有主键在(c1, c2, c3)上:

CREATE TABLE t1 (
  c1 INT, c2 INT, c3 INT, c4 CHAR(100),
  PRIMARY KEY(c1,c2,c3)
);

在下面这个查询中,这个WHERE条件使用了索引的所有列。但是,行构造函数本身不包含索引前缀,结果是优化器仅使用c1,(key_len=4, the size of c1):

mysql> EXPLAIN SELECT * FROM t1
       WHERE c1=1 AND (c2,c3) > (1,1)\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: const
         rows: 3
     filtered: 100.00
        Extra: Using where

在这种情况下,使用等效的非构造函数表达式重写行构造函数表达式可能会使用更完整的索引。对于给定的查询,行构造函数和等效的非构造函数表达式是:

(c2,c3) > (1,1)
c2 > 1 OR ((c2 = 1) AND (c3 > 1))

重写查询以使用非构造函数表达式会导致优化程序使用索引中的所有三列:

mysql> EXPLAIN SELECT * FROM t1
       WHERE c1 = 1 AND (c2 > 1 OR ((c2 = 1) AND (c3 > 1)))\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 12
          ref: NULL
         rows: 3
     filtered: 100.00
        Extra: Using where

因此,为了获得更好的结果,请避免将行构造函数与AND/OR表达式混合。 使用其中一个。

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Client does not support authentication protocol requested by server; consider upgrading MySQL client jdk.internal.reflect.GeneratedConstructorAccessor15.newInstance(Unknown Source) java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480) com.mysql.jdbc.Util.handleNewInstance(Util.java:411) com.mysql.jdbc.Util.getInstance(Util.java:386) com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013) com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609) com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541) com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:943) com.mysql.jdbc.MysqlIO.secureAuth411(MysqlIO.java:4113) com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1308) com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2336) com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2369) com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2153) com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:792) com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47) jdk.internal.reflect.GeneratedConstructorAccessor12.newInstance(Unknown Source) java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480) com.mysql.jdbc.Util.handleNewInstance(Util.java:411) com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:381) com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:305) com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1375) com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1431) com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:1844)
最新发布
06-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值