我正要编写一个包含WHERE isok=1
. 顾名思义,isok
是一个布尔字段(实际上TINYINT(1) UNSIGNED
是根据需要设置为 0 或 1 的 a)。
索引该字段是否有任何性能提升?引擎(在这种情况下为 InnoDB)在查找索引时的性能会更好还是更差?
只是在这里对其他几个答案提出更详细的说明,因为根据我的经验,那些查看此类问题的人与我们在同一条船上,我们都听说索引布尔字段是没有意义的,但是......
我们有一个大约有 400 万行的表,一次只有大约 1000 行左右会标记一个布尔开关,这就是我们搜索的内容。在我们的布尔字段上添加索引将查询速度提高了几个数量级,从大约 9 多秒到几分之一秒。
并不真地。你应该把它当作一本书来思考。如果一本书中只有 3 种单词并且您将它们全部编入索引,那么您的索引页数将与普通页数相同。
如果一个值的记录相对较少,则会有性能提升。例如,如果您有 1000 条记录,其中 10 条为 TRUE,那么如果您使用isok = 1
正如迈克尔杜兰特所提到的,它也使写入速度变慢。
编辑:可能的重复:索引布尔字段
在这里它解释说,即使你有一个索引,如果你有太多的记录,它也不会使用索引。 MySQL 在检查 = 1 时不使用索引,而是在 = 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 可以快速确定要在数据文件中间查找的位置,而无需查看所有数据。
我认为在这种情况下说索引不会降低性能也是安全的,所以你只需要从中获益。
索引只是一张地图。检索所有将 is_xxx 设置为 true 的行是 O(1)。没有它,您需要扫描整个表并针对其中的每一行检查此谓词,即 O(n)