54

我主要是一名 Actionscript 开发人员,绝不是 SQL 专家,但有时我必须开发简单的服务器端东西。所以,我想我会问更有经验的人关于标题中的问题。

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

那么,我应该将此列设为索引吗?

作为记录,我使用的是 Mysql 5,但我更感兴趣的是为什么它会/没有意义索引一个我知道基数较低的列。

提前致谢。

4

5 回答 5

93

如果满足以下条件,索引甚至可以帮助处理低基数字段:

  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则需要 a。尽管它对 进行了一些优化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性能问题不大,那么创建索引是安全的。

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

于 2010-01-21T22:10:45.533 回答
10

在复合索引中包含布尔字段可能是值得的。例如,如果您有一个通常需要按日期排序的大型消息表,但您也有一个布尔已删除字段,因此您经常像这样查询它:

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

您肯定会从已删除日期字段上的复合索引中受益。

于 2010-01-21T21:55:36.457 回答
3

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

于 2010-01-21T21:50:04.223 回答
3

当一半的记录值为 1 而另一半为 0 时,没有必要在该列上放置索引。查询优化器可能不会使用它。

但是,通常情况下,您有一小部分“活动”记录和越来越多的“非活动”记录。例如,在错误跟踪系统中,您关心活动的错误,而几乎每次都查看已完成和归档的错误。对于这种情况,诀窍是使用“dateInactivated”列来存储记录被停用/删除时的时间戳。顾名思义,当记录处于活动状态时,该值为NULL,但一旦停用,则写入系统日期时间。因此,随着“已删除”记录数量的增加,该列上的索引最终具有高选择性,因为每条记录都将具有唯一的(不是严格意义上的)值。查询将有

"... AND dateInactivated is NULL ..." 

作为谓词的一部分,索引将拉入您关心的正确行集。

于 2019-07-10T05:23:57.280 回答
2

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

在 50% 时,我可能会在有/没有的情况下进行一些基准测试,看看它是否有很大的不同。

于 2010-01-21T21:51:01.413 回答