2010-01-21 64 views
29

我主要是一个Actionscript开发人员,决不是SQL专家,但有时我不得不开发简单的服务器端的东西。所以,我想我会问更多有经验的人关于标题中的问题。使用基数较低的索引是否有意义?

我的理解是,通过在一个只包含几个不同值的列中设置索引,你并不会获得太多收益。我有一个列保存一个布尔值(实际上它是一个小的int,但我用它作为标志),并且这个列用于大多数查询的WHERE子句中。在理论上的“平均”情况下,一半的记录值将为1,另一半为0.因此,在这种情况下,数据库引擎可以避免全表扫描,但是无论如何都必须读取很多行(总排/ 2)。

那么,我应该让这个列成为索引吗?

为了记录,我使用的是Mysql 5,但是我更关心为什么它没有意义地索引一个列,我知道这将有一个低基数的一般理由。

在此先感谢。

回答

2

我通常会做一个简单的“有索引”vs“不要”索引测试。根据我的经验,您可以在使用ORDER BY索引列的查询中获得大部分性能。如果您对该列进行了任何排序,索引最有可能有所帮助。

+0

感谢您的回答。在这种情况下,我并未在该列上排序。它只是将记录标记为启用/禁用。基本上,我将它用于软删除。这就是为什么我必须在大多数查询的WHERE子句中使用它。 – 2010-01-21 21:58:10

2

恕我直言,它的用处有限。我认为在大多数情况下,除了可能帮助更多的标志之外,您在查询中还使用了其他标准。

在50%的时候,我可能会做一些基准测试,看看它是否有很大的不同。

8

在组合索引中包含布尔值字段可能是值得的。例如,如果你有这通常需要按照日期来排序消息的大表,但你也有一个布尔删除领域,所以你经常查询这样的:

SELECT ... FROM Messages WHERE Deleted = 0 AND Date BETWEEN @start AND @end 

你一定会能从中受益删除日期字段上的复合索引。

+0

谢谢。也许我应该对复合指数做一些研究(我只知道存在,但并没有真正使用它们)。我以非常类似于示例代码的方式使用此列(尽管存在连接和其他内容,但WHERE子句始终具有用于标记软删除的此标志)。 – 2010-01-21 22:03:53

56

索引可以帮助甚至在低基数的域,如果:

  1. 相较于其他值可能值之一是非常罕见的,你搜索。

    举例来说,很少有色盲的女性,所以这个查询:

    SELECT * 
    FROM color_blind_people 
    WHERE gender = 'F' 
    

    将最有可能从指数上gender受益。

  2. 当值倾向于在表的顺序进行分组:

    SELECT * 
    FROM records_from_2008 
    WHERE year = 2010 
    LIMIT 1 
    

    虽然这里只有3不同的几年,是最有可能加入前几年记录第一所以很多记录必须是如果不是索引,则在返回第一个2010记录之前进行扫描。

  3. 当你需要ORDER BY/LIMIT

    SELECT * 
    FROM people 
    ORDER BY 
         gender, id 
    LIMIT 1 
    

    没有索引,filesort将需要。尽管对LIMIT做了一些优化,但它仍然需要全表扫描。

  4. 当指数涵盖了在查询中使用的所有字段:

    CREATE INDEX (low_cardinality_record, value) 
    
    SELECT SUM(value) 
    FROM mytable 
    WHERE low_cardinality_record = 3 
    
  5. 当你需要DISTINCT

    SELECT DISTINCT color 
    FROM tshirts 
    

    MySQL将使用INDEX FOR GROUP-BY,如果你有几种颜色,此查询即使拥有数百万条记录也会立即实现。

    这是低基数字段上的索引是更多高于基数高字段时的情况。

注意,如果DML性能没有太大的问题,那么就可以安全地创建索引。

如果优化器认为索引效率低下,索引就不会被使用。

相关问题