1

我有几个表需要获取与 foo 相关的数据。表格的大小约为 10^8 行。

所以我需要从这些表中获取该列包含子字符串“foo”的所有行。

select * from bar where my_col like '%foo%';

我知道这很慢,所以我检查了可能的值:

select distinct my_col from bar where my_col like '%foo%';
-- => ('xx_foo', 'yy_foo', 'xx_foo_xx', 'foo' ... 'xx_foo_yy')

可能值的数量在 3 到 20 之间变化。

现在 '%foo%' 到底有多慢?

select * from bar where my_col like '%foo%';
-- or
select * from bar where my_col in('foo', 'xx_foo' ... 'foo_yy'); -- list_size = 20

关于何时使用什么的任何一般规则,或者测试不同情况的速度是唯一的方法?

编辑:我不拥有该表,并且 foo 列上不存在索引。所以无论如何它都需要进行全表扫描。

4

2 回答 2

1

如果使用%foo%,则会进行全表扫描,速度很慢。

如果您使用IN值列表,则如果索引存在于您具有条件的列上,则可以使用索引。

所以,如果可以的话,你应该避免使用%foo%. 根据新值出现在表中的频率,您可能会考虑使用一个额外的表来保存不同的值并在查询主表时使用它,并在新的不同值出现时更新该额外的表(如果可能在你的设计)。

于 2013-10-11T08:56:17.877 回答
1

当模式以 . 开头时,使用运算符的搜索like肯定会导致表扫描%。当使用in运算符并且值不超过表中值的百分之几时,可以使用索引(如果存在)。检查基数概念:

http://en.wikipedia.org/wiki/Cardinality_%28SQL_statements%29

DBMS 知道保留有关表的统计信息的基数。如果您的列具有高基数并且上面有索引,那么在使用in运算符时可能会进行索引扫描。要更新统计信息,请发出analyze命令。

于 2013-10-11T08:56:43.207 回答