AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 52156
Accepted
Mike Purcell
Mike Purcell
Asked: 2013-10-25 13:08:53 +0800 CST2013-10-25 13:08:53 +0800 CST 2013-10-25 13:08:53 +0800 CST

MySQL - 向低基数文本列添加索引?

  • 772

我正在处理将枚举列转换为文本列的项目(我无法更改)。该列的基数很低(7 个唯一值)。我会通过添加 10-15 char 索引来提高性能,还是基数足够低,索引会导致收益递减?

mysql performance
  • 2 2 个回答
  • 3887 Views

2 个回答

  • Voted
  1. Best Answer
    RolandoMySQLDBA
    2013-10-25T13:26:57+08:002013-10-25T13:26:57+08:00

    列的大小或数据类型无关紧要。重要的是独特的价值观。如果您只有 7 个唯一值,则意味着必须考虑 14.286% 的行。

    与其给 MySQL Query Optimizer 解决这个问题的压力,不如通过散列对表进行分区:

    CREATE TABLE mytable
    (
        id INT NOT NULL AUTO_INCREMENT,
        ...
        ...
        myenum INT NOT NULL,
        PRIMARY KEY (id)
    )
    PARTITION BY HASH( myenum )
    PARTITIONS 7;
    

    不需要在任何索引中都有 myenum。如果任何 SELECT 查询的WHERE子句包含AND myenum = ....

    如果您必须增加唯一值的数量,则必须增加分区的数量。

    试试看 !!!

    更新 2013-10-24 17:57

    正如我在评论中所说,您应该按基数最高的枚举进行分区。

    其他枚举呢?不要自己索引枚举!

    如果您的 SELECT 查询包括 WHERE enum2...AND enum3=...`` AND enum4=...`,您应该考虑创建枚举的复合索引。

    例如,如果您有 enum2、enum3 和 enum4,您可以制作如下复合索引:

    ALTER TABLE mytable ADD INDEX (enum2,enum3,enum4);
    ALTER TABLE mytable ADD INDEX (enum3,enum4);
    

    你应该选择哪个顺序?

    • 基数(枚举2)>基数(枚举3)
    • 基数(enum3) > 基数(enum4)

    CAVEAT:再次强调,如果您按 分区enum1,则无需在enum1.

    • 4
  2. Michael - sqlbot
    2013-10-25T17:54:17+08:002013-10-25T17:54:17+08:00

    由于两个原因,我几乎不能不同意接受的答案。

    首先,所有关于优化器不使用低基数索引的讨论都被夸大了。确实,优化器可能不喜欢它,而且优化器有时可能会选择忽略它,但我看到帖子暗示如果超过“x”% 的行与索引匹配,则不会使用它。这绝对不是真的。

    我坐在一张超过一百万行的桌子前。它有一个索引枚举列,以及许多其他索引,但我在下面显示了该索引。注意基数是 2。

    mysql> show indexes in xxxxxxx;
    +---------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | Table   | Non_unique | Key_name            | Seq_in_index | Column_name         | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
    +---------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | xxxxxxx |          1 | target_xxx          |            1 | target_xxx          | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
    +---------+------------+---------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    

    那么,优化器是否使用该索引?

    mysql> explain select * from xxxxxxx where target_xxx = 'default';
    +----+-------------+---------+------+---------------+------------+---------+-------+---------+-----------------------+
    | id | select_type | table   | type | possible_keys | key        | key_len | ref   | rows    | Extra                 |
    +----+-------------+---------+------+---------------+------------+---------+-------+---------+-----------------------+
    |  1 | SIMPLE      | xxxxxxx | ref  | target_xxx    | target_xxx | 1       | const | 1269015 | Using index condition |
    +----+-------------+---------+------+---------------+------------+---------+-------+---------+-----------------------+
    1 row in set (0.23 sec)
    

    是的,它确实。它对匹配的行使用索引,并且它还使用索引几乎立即告诉我,如果我在 where 子句中使用了在该列的表中的任何位置都找不到的值,则没有行匹配。

    低基数索引没有用或被使用的神话......严重需要被丢弃。

    给优化器选择。这不是你想要避免的事情。

    其次,如果您按照讨论对表进行分区,那么在其 where 子句中未引用该列的每个查询现在都需要处理所有 7 个分区(和 7 组索引)。除非此列有一些真正重要和有意义的东西,这意味着您将在大多数 where 子句中询问它,否则对它进行分区似乎不是一个特别好的计划。

    分区不是灵丹妙药。

    然而,它是另一种子弹——除非使用得当,否则它往往会指向你的脚。

    • 4

相关问题

  • 我在哪里可以找到mysql慢日志?

  • 如何优化大型数据库的 mysqldump?

  • 什么时候是使用 MariaDB 而不是 MySQL 的合适时机,为什么?

  • 组如何跟踪数据库架构更改?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    授予用户对所有表的访问权限

    • 5 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve