2 where子句比分离查询慢

问题描述 投票:0回答:2

我正在使用Google Cloud SQL(微服务器版本)来运行几项性能测试。

我想做以下查询:

select count(*) from table where A = valueA and B like "%input_string%";
+----------+
| count(*) |
+----------+
|   512997 |
+----------+
1 row in set (9.64 sec)

如果我单独运行它们,我得到:

select count(*) from table where A = valueA;
+----------+
| count(*) |
+----------+
|   512998 |
+----------+
1 row in set (0.18 sec)

select count(*) from table where B like "%input_string%";
+----------+
| count(*) |
+----------+
|   512997 |
+----------+
1 row in set (1.43 sec)

这种性能差异怎么可能?

A和B列都具有索引,因为它们用于在Web应用程序中对表进行排序。

谢谢!编辑:表架构

table | CREATE TABLE `table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `A` varchar(9) DEFAULT NULL,
  `B` varchar(50) DEFAULT NULL,
  `C` varchar(10) DEFAULT NULL,
  `D` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `A` (`A`),
  KEY `B` (`B`)
) ENGINE=InnoDB AUTO_INCREMENT=512999 DEFAULT CHARSET=utf8
mysql query-optimization google-cloud-sql database-performance
2个回答
1
投票

一个选项可能是使用FULLTEXT INDEX并使用MATCH()

CREATE TABLE `table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `A` varchar(9) DEFAULT NULL,
  `B` varchar(50) DEFAULT NULL,
  `C` varchar(10) DEFAULT NULL,
  `D` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY(A), 
  FULLTEXT INDEX(B)
) ENGINE=InnoDB AUTO_INCREMENT=512999 DEFAULT CHARSET=utf8

并重写一个查询

SELECT 
 count(*)
FROM 
`table`
WHERE
   A = 'A'
 AND 
   B IN (

     SELECT 
      B
     FROM 
      `table`
     WHERE
   MATCH(B) AGAINST('+input_string' IN BOOLEAN MODE)
)

内部SQL将根据FULLTEXT索引过滤掉可能的结果。 外部SQL将执行其他过滤。

你现在也可以使用UNION ALL。 它应该在CREATE TABLE这个问题上发表意见。 一般的想法是为两个过滤器获得两个计数,并选择最低的有效计数。

询问

SELECT 
 MIN(counted) AS 'COUNT(*)' # Result 512997
FROM (

  select count(*) AS counted from `table` where A = 'A' # Result 512998
  UNION ALL
  select count(*)  from `table` where B like "%input_string%" # Result  512997
) AS counts

0
投票

你有两次跑步吗?如果没有,可能会有缓存,让您感到困惑。

where A = valueA and B like "%input_string%";乞求INDEX(A, B)。注意:该复合索引不等同于您的两个单独索引。

如果你在FULLTEXT上使用B指数,那么这将更简单:

SELECT COUNT(*) FROM t
    WHERE MATCH(B) AGAINST('+input_string' IN BOOLEAN MODE)
      AND A = valueA

(使用子查询应该是不必要的并且速度较慢。)

© www.soinside.com 2019 - 2024. All rights reserved.