【问题标题】:Proper Indexing MySQL正确索引 MySQL
【发布时间】:2012-01-30 00:58:01
【问题描述】:

就索引而言,索引所有将要搜索的字段(在 WHERE 子句中)以加快 SELECTS 是否合适?例如,我的数据库包含一个配置文件表,该表存储用户信息,例如姓名、兴趣代码、zip、描述和电子邮件。配置文件记录由与 userid 唯一对应的 PRIMARY id 列标识。我将 zip 和 intrestCode 作为索引,因为配置文件将通过 zip 和可能的 intrestCode(SELECT `blah`,`blah`... FROM profile WHERE zip=?SELECT `blah`,`blah`... FROM profile WHERE zip=? && intrestCode=?)进行搜索。我做得对吗?

【问题讨论】:

    标签: php mysql indexing


    【解决方案1】:

    听起来基本正确。你应该知道,你不能在同一个查询中对同一个表使用两个不同的索引,所以如果你跑了

    CREATE INDEX `zip` ON `profile` (`zip`);
    CREATE INDEX `intrestCode` ON `profile` (`intrestCode`);
    

    然后查询

    SELECT `blah`,`blah`... FROM profile WHERE zip=? && intrestCode=?
    

    只能从索引中查找一张表。这里的秘密是您可以在两个表上创建一个索引,如下所示:

    CREATE INDEX `zip+intrestCode` ON `profile` (`zip`, `intrestCode`);
    

    MySQL 可以将其用于在 WHERE 子句中单独使用 zip 或同时使用 zipintrestCode 的查询,但不能用于在 WHERE 子句中仅使用 intrestCode 的查询。

    (这是因为每个索引都覆盖了整个表。如果 MySQL 尝试从不同的表中查找 zipintrestCode,那么它将从第二个索引中检索大量不相关的行。因此,它只查看一个索引。如果您希望它使用两列上的索引,则需要一个包含两列的索引。)

    【讨论】:

    • 问题是我不知道用户想要如何搜索。有些人可能只想按邮政编码搜索,有些人可能只想按兴趣搜索,有些人可能希望两者都搜索。这似乎是一个普遍现象。没有解决方案(缺少很多表)?构建多列索引并通配未使用的字段会起作用吗?仅适用于 Zip:SELECT * FROM profiles where zip = ? && 兴趣代码 LIKE '%'。仅适用于 Intrest 代码:SELECT * from profiles WHERE zip LIKE '%' && intrestCode = ?。对于两者: SELECT * from profiles WHERE zip = ? && intrestCode=?.
    • 没有。字段之间必须有严格的关系。如果您有两个字段,您可以轻松创建两个索引,一个在zipintrestCode 上,一个在intrestCode 上。如果您有更多字段,则很难解释所有组合。此时最好为每个字段创建一个索引并让优化器选择最好的索引(尽管您无法获得相同的效率增益)。根据数据库的大小,创建多列索引可能根本不值得。这里需要一些判断调用。
    • 还有一个问题,添加多个索引来涵盖许多组合实际上会减慢速度(来 UPDATE、INSERT 甚至 SELECT 时间?),或者它只是在磁盘空间方面成本高昂。由于成本低,磁盘空间几乎是无限资源。
    • 它在 UPDATE 和 INSERT 时会减慢速度,但可能只是一点点(除非您的表非常大,在这种情况下,您可以从 SELECT 时拥有大量索引中获得很大的优势)。这主要是磁盘空间的问题。但是,如果您有很多列,则需要小心创建过多索引,因为您将创建的索引数量会随着列数呈指数增长。
    【解决方案2】:

    索引关系数据库是一门艺术。最好的方法是查看您将要进行的所有不同查询,并将索引放在所涉及的列上。使用EXPLAIN 查看查询将使用哪些索引。

    但是,请记住 MySQL 一次只能使用表中的一个索引。这就是为什么您可以一次在多个列上放置索引的原因。如果 MySQL 只需要索引开头的列,它可以使用多列索引。在您的示例中,我会将多列索引 zipintrestCode 放在一起,因为这将有助于两个查询。这样您就不需要在 zip 上单独建立索引。

    【讨论】:

    • 那么如何加快 SELECT email,name FROM profiles WHERE zip = ? && intrestCode = ? .如您所见,它使用 2 列。我不会使用 2 个单独的索引?
    • 你做一个多列索引:ALTER TABLE profile ADD INDEX (zip, intrestCode)
    【解决方案3】:

    我相信基本上是的。您应该监控您的数据库以遇到更多问题,并根据结果优化您的查询和表。

    【讨论】:

      【解决方案4】:

      通常,您希望将索引添加到您将加入或包含在 where 子句中的列。请记住,两列上的索引不同于两列中每一列上的索引。此外,如果您在多列上有索引,则顺序很重要。

      假设你有两列 A 和 B,并且有一个两列索引,顺序是 A 然后 B。有三种情况:

      1. 针对 A 列的 Where 子句:使用了索引
      2. 针对 B 列的 Where 子句:未使用索引
      3. 针对 A 列和 B 列的 Where 子句:使用了索引

      就像 staticsan 所说,索引是一门艺术,没有任何规则可以 100% 应用。使用解释计划查看查询的执行情况并进行相应的调整。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多