关于何时使用索引有用,是否有一般的经验法则或公式?
例如,在以下情况中,在id
列上添加INDEX是显而易见的:
SELECT * FROM table WHERE id = '1iuhiasdf89384h'
但是,如果is_qualified
有两个可能的值,则以下内容可能无效:
SELECT * FROM table WHERE is_qualified=1
具有10 [0-9]个可能值的项目怎么样? 100个值[0-99]?您何时通常想要添加索引,以及这与cardinality
?
答案 0 :(得分:2)
作为一般经验法则,优化程序选择在where
子句中使用索引的原因是减少正在读取的数据页数。因此,如果您的数据在页面上随机分布,那么重要的问题是每页上有多少条记录以及过滤器选择了多少条记录。
假设每页有100条记录。然后,随机选择百分之一的记录将可能(几乎)选择所有页面。在这种情况下,读取页面并对页面进行过滤可能比使用索引更快,因为无论如何几乎所有数据页面都将被读取。 Ť
因此,对于大多数表来说,返回一个或少量记录的查询最好使用索引。返回大量记录的查询可能无法从索引中受益。一个必然结果是,对于小型表,索引可能永远不会有用。如果数据适合一个页面,使用where
过滤器扫描页面的速度可能与使用索引一样快。
也就是说,如果查询的选择性大于数据页面上平均记录数的倒数,则索引可能不会有用。这与“一般”规则尽可能接近,但请继续阅读。
索引的类型也有所不同。如果条件为is_qualified
并且只有0.1%的记录符合此条件,则索引可能会有用。或者,如果1%是合格但记录非常大,因此页面上只有10个,那么索引可能很有用。或者,如果is_qualified
是聚集索引中的第一列,则1
的所有值都位于少数几个页面上。使用聚簇索引,即使is_qualified = 1
的选择性为30%也意味着只读取30%的数据页 - 这应该将许多查询的时间减少三分之二。
当然,这样就不会使用索引进行连接和排序 - 甚至100%的选择性仍然可以从索引中获益。但是,您的问题似乎是针对where
子句中的过滤。
答案 1 :(得分:1)
我认为你需要做一些研究和阅读使用索引。即使从你自己的例子中,你也希望得到一个关于" id"的索引。因为你正在寻找一个特定的ONE ...但是在IS_QUALIFIED上有一个索引并不重要,因为它只能有两个可能的值...但是带有字母数字的ID可能有数十亿的值。
索引用于帮助您快速缩小范围并查找记录,而无需根据您希望提取的常用条件访问原始数据页以提取合格记录。根据您希望运行的常见查询类型,索引应该被视为甚至包含多个列。
让我们看一些你的数据场景列,假设一个表是一个子表,每个" id",有" is_qualified"和" othertype" (你的价值观0-9),以及其他一些东西......也许是某些东西的日期,或者"其他类型的描述"。
如果你只有一个ID的索引,那么所有" ID"记录将被组合在一起,这很好,一旦你到达他们快速浏览那些得到你的结果。
但现在,假设您正在寻找所有具有" Is_Qualified" = 1 AND"其他类型"列是3.你不能快速得到它们,没有相互之间的相关性...但是如果你有一个多重键索引(is_qualified,othertype,id),那么你可以快速跳转到那些Is_Qualified = 1和othertype = 3的记录,然后您已准备好所有ID。
将此应用于一个有几百万条记录要查询的表,并运行没有索引的查询,您将非常欣赏它们的用途,并学会设计好的,有意义的索引。
答案 2 :(得分:0)
更重要的是,表中存在多少行,而不是它们是否具有2或10个可能的值。对于少于200-300行的表,不需要索引。如果你有100万行,即使列只有0和1,最好有索引 - 你将避免完全扫描。例如,如果只有500个1M行是1 - 查询将跳过扫描999,500行。