【发布时间】:2012-05-18 11:22:08
【问题描述】:
我正要编写一个包含WHERE isok=1 的查询。顾名思义,isok 是一个布尔字段(实际上是一个 TINYINT(1) UNSIGNED,根据需要设置为 0 或 1)。
索引该字段是否有任何性能提升?引擎(在这种情况下为 InnoDB)在查找索引时的性能会更好还是更差?
【问题讨论】:
-
Indexing boolean fields 的可能重复项
我正要编写一个包含WHERE isok=1 的查询。顾名思义,isok 是一个布尔字段(实际上是一个 TINYINT(1) UNSIGNED,根据需要设置为 0 或 1)。
索引该字段是否有任何性能提升?引擎(在这种情况下为 InnoDB)在查找索引时的性能会更好还是更差?
【问题讨论】:
只是在这里对其他几个答案进行更详细的说明,因为根据我的经验,那些查看此类问题的人与我们在同一条船上,我们都听说索引布尔字段毫无意义,但是.. .
我们有一个包含大约 400 万行的表,一次只有大约 1000 行左右会标记一个布尔开关,这就是我们搜索的内容。在我们的布尔字段上添加索引可以将查询速度提高几个数量级,从大约 9 多秒缩短到几分之一秒。
【讨论】:
WHERE my_col > 0 而不是 my_col = 1 似乎也有助于提高速度
不是真的。你应该把它当作一本书来思考。如果一本书中只有 3 种单词并且您将它们全部编入索引,那么您的索引页数将与普通页数相同。
如果一个值的记录相对较少,则会提高性能。例如,如果您有 1000 条记录,其中 10 条为 TRUE,那么使用 isok = 1 搜索会很有用
正如迈克尔·杜兰特所说,它也会使写入速度变慢。
编辑:可能重复:Indexing boolean fields
这里解释了即使你有一个索引,如果你有太多的记录,它也不会使用索引。 MySQL not using index when checking = 1 , but using it with = 0
【讨论】:
这取决于实际查询和索引/查询组合的选择性。
案例A:条件WHERE isok = 1,没有其他内容:
SELECT *
FROM tableX
WHERE isok = 1
如果索引有足够的选择性(假设您有 1M 行,而只有 1k 行有 isok = 1),那么 SQL 引擎可能会使用索引并且比不使用它更快。
如果索引的选择性不够(比如你有 1M 行,超过 100k 有isok = 1),那么 SQL 引擎可能会不使用索引并做一个表扫描。
案例 B:条件 WHERE isok = 1 和更多内容:
SELECT *
FROM tableX
WHERE isok = 1
AND another_column = 17
然后,这取决于您还有哪些其他索引。 another_column 上的索引可能比isok 上的索引更具选择性,后者只有两个可能的值。 (another_column, isok) 或 (isok, another_column) 上的索引会更好。
【讨论】:
这取决于数据的分布。
想象一下,我有一本书,有 1000 页紧密打印的页面,而我书中唯一的词是“是”和“否”,一遍又一遍地重复并随机分布。如果我被要求圈出所有“是”的实例,书后的索引会有所帮助吗?视情况而定。
如果是和否是随机分布的,那么在索引中查找将无济于事。索引会使这本书变得更大,无论如何我会更快地从前面开始,通过每一页寻找“是”的所有实例并圈出它们,而不是查找每个项目索引,然后将索引条目的引用指向它所引用的页面。
但是,如果在我这千页的书中只有十个“是”实例,而其他所有内容都只是数百万个“否”,那么索引将节省我大量时间来查找这十个“是”实例并绕着他们转。
在数据库中也是如此。如果是 50:50 分布,那么索引将无济于事 - 数据库引擎最好从头到尾遍历数据(全表扫描),索引只会使数据库更大,并且写入和更新速度较慢。但是,如果它类似于 4000:1 分布(根据此线程中的 oucil),那么如果它是您要查找的 4000 个项目中的 1 个,则索引查找可以大大加快它.
【讨论】:
不,通常不会。
当它们具有高选择性/基数时,您通常会为搜索建立索引。 在大多数表中,布尔字段的基数非常低。 它还会使您的写入速度稍微变慢。
【讨论】:
实际上,这取决于您运行的查询。但是,通常是的,以及索引任何其他类型的字段。
【讨论】:
是的,索引会提高性能,请检查 EXPLAIN 有无索引的输出。
来自文档:
索引用于快速查找具有特定列值的行。如果没有索引,MySQL 必须从第一行开始,然后读取整个表以查找相关行。表越大,成本越高。如果表中有相关列的索引,MySQL 可以快速确定要在数据文件中间查找的位置,而无需查看所有数据。
我认为在这种情况下,可以肯定地说索引不会降低性能,因此您只需从中获益。
【讨论】:
TINYINT(1) UNSIGNED列,数据的大小会很小。
索引只是一张地图。检索所有将 is_xxx 设置为 true 的行是 O(1)。没有它,您需要扫描整个表并针对其中的每一行检查此谓词,即 O(n)
【讨论】: