MySQL where or composite index : 执行两个单独的搜索时会更快吗?
MySQL where or composite index : will it be faster when performing two separate search?
我有以下 table:
CREATE TABLE `FooBar` (
`id` int,
`foo` int,
`bar1` int,
`bar2` int,
PRIMARY KEY (`id`),
KEY `foobar1` (`foo`, `bar1`),
KEY `foobar2` (`foo`, `bar2`)
) ENGINE=InnoDB;
现在我有以下 select 查询:
select * from FooBar where foo=1 and (bar1=2 or bar2=2);
和备选两个连续的selects
select * from FooBar where foo=1 and bar1=2;
select * from FooBar where foo=1 and bar2=2;
与连续两个 select 的总时间相比,带有“或”的单个 select 的时间会明显更快、更慢还是大致相同?
都没有。
- OR 会降低性能——通常会导致忽略索引并扫描整个 table。
- 两个单独的查询——处理一个语句有很多开销;合并两个语句通常要好得多(除非这会导致其他低效率)。
OR
的通常加速比是 UNION
:
( select * from FooBar where foo=1 and bar1=2 )
UNION ALL
( select * from FooBar where foo=1 and bar2=2 )
;
UNION ALL
比 UNION DISTINCT
快,但 ALL
可能导致重复行。相应地选择。
(如果会有ORDER BY
或者分页,讨论会变长。)
如果 bar1
和 bar2
是跨列分布的“数组”的示例,这将成为 not 以这种方式设计架构的论据.相反,这可能更好,因为 table 有一个“条形”列,并且每个 foo
.
有(可能)多行
一个简单的例子是 table 个人,您希望在其中包含他们的 phone 号码。最好有一个 table 和 (person_id, phone_num) -- 号码可以是手机、固定电话、传真、工作、家庭等。它是开放式、零个或多个等
时间...没错,只有几行数据会随着数据的增长而难以预测性能。这是一个技巧;它计算涉及的行数,因此可以很容易地发现 OR
触及 table 中的每一行: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#handler_counts -- 20 行应该没问题。如果处理程序计数为 19 或 20,则它进行了 table 扫描。大约 40 表示 2 次扫描。我预测
- 20 用于您的
OR
查询;
- 2 用于您的两个单独的选择(但这并未考虑每个查询的开销)
- 2 我的
UNION ALL
- 我的
UNION DISTINCT
4 或 6,加上 2 次写入(对于必要的临时 table)。
20 显然不能很好地扩展到数百万行;其余的都会。
EXPLAIN
有很多计数问题。尽管如此,在这种情况下,它可能几乎和我的 Handler 技术一样好。
没有工具可以告诉您“您应该做什么”。 (Whosebug 很接近,但它非常耗费人力。)
我有以下 table:
CREATE TABLE `FooBar` (
`id` int,
`foo` int,
`bar1` int,
`bar2` int,
PRIMARY KEY (`id`),
KEY `foobar1` (`foo`, `bar1`),
KEY `foobar2` (`foo`, `bar2`)
) ENGINE=InnoDB;
现在我有以下 select 查询:
select * from FooBar where foo=1 and (bar1=2 or bar2=2);
和备选两个连续的selects
select * from FooBar where foo=1 and bar1=2;
select * from FooBar where foo=1 and bar2=2;
与连续两个 select 的总时间相比,带有“或”的单个 select 的时间会明显更快、更慢还是大致相同?
都没有。
- OR 会降低性能——通常会导致忽略索引并扫描整个 table。
- 两个单独的查询——处理一个语句有很多开销;合并两个语句通常要好得多(除非这会导致其他低效率)。
OR
的通常加速比是 UNION
:
( select * from FooBar where foo=1 and bar1=2 )
UNION ALL
( select * from FooBar where foo=1 and bar2=2 )
;
UNION ALL
比 UNION DISTINCT
快,但 ALL
可能导致重复行。相应地选择。
(如果会有ORDER BY
或者分页,讨论会变长。)
如果 bar1
和 bar2
是跨列分布的“数组”的示例,这将成为 not 以这种方式设计架构的论据.相反,这可能更好,因为 table 有一个“条形”列,并且每个 foo
.
一个简单的例子是 table 个人,您希望在其中包含他们的 phone 号码。最好有一个 table 和 (person_id, phone_num) -- 号码可以是手机、固定电话、传真、工作、家庭等。它是开放式、零个或多个等
时间...没错,只有几行数据会随着数据的增长而难以预测性能。这是一个技巧;它计算涉及的行数,因此可以很容易地发现 OR
触及 table 中的每一行: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#handler_counts -- 20 行应该没问题。如果处理程序计数为 19 或 20,则它进行了 table 扫描。大约 40 表示 2 次扫描。我预测
- 20 用于您的
OR
查询; - 2 用于您的两个单独的选择(但这并未考虑每个查询的开销)
- 2 我的
UNION ALL
- 我的
UNION DISTINCT
4 或 6,加上 2 次写入(对于必要的临时 table)。
20 显然不能很好地扩展到数百万行;其余的都会。
EXPLAIN
有很多计数问题。尽管如此,在这种情况下,它可能几乎和我的 Handler 技术一样好。
没有工具可以告诉您“您应该做什么”。 (Whosebug 很接近,但它非常耗费人力。)