【问题标题】:How many indexes should be created for faster queries应该为更快的查询创建多少索引
【发布时间】:2010-09-20 08:29:21
【问题描述】:

我的对象模型如下所示,并希望您输入要创建的索引数量以加快查询响应(在 h2、mysql 上)。以下模型给出了假设和问题。

@Entity
@Table(name = "user")
public class User  {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false, insertable = false, updatable = false)
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY)
    @ForeignKey(name = "fk_user_org_id")
    @Index(name = "idx_user_org_id")
    @JoinColumn(name = "org_id", nullable = false, referencedColumnName = "id")
    @NotNull
    private Organization organization;

    @ManyToOne(fetch = FetchType.LAZY)
    @ForeignKey(name = "fk_user_year_id")
    @Index(name = "idx_user_year_id")
    @JoinColumn(name = "year", nullable = false, referencedColumnName = "id")
    @NotNull
    private Year year;

    @ManyToOne(fetch = FetchType.LAZY)
    @ForeignKey(name = "fk_user_created_by")
    @Index(name = "idx_user_created_by")
    @JoinColumn(name = "created_by", nullable = false, referencedColumnName = "id")
    @NotNull
    private User createdBy;

    @Column(name = "name", nullable = false)
    private String name;

    @Column(name = "desc")
    private String desc;

    @Column(name = "is_system", length = LEN_1)
    @Type(type = "org.hibernate.type.YesNoType")
    private boolean isSystem = false;

    @Column(name = "user_type", nullable = false)
    private UserType userType;

    @Column(name = "status", nullable = false)
    @NotNull
    private Status status;

}

我们的计划是使用多列索引而不是单列索引(即根据 (organization, year, isSystem, status, userType, createdBy) 创建索引 user_idx)。假设我有这个索引,我会得到下面列出的查询的优化响应吗?

  1. select * from user where organization=1 and year=2010;
  2. select * from user where organization=1 and year=2010 and isSytem=true or false; (即系统用户或应用程序定义的用户)
  3. select * from user where organization=1 and year=2010 and isSytem=false and userType=Manager(即所有经理)
  4. select * from user where organization=1 and year=2010 and isSytem=false and userType=Employee(即所有员工)
  5. select * from user where organization=1 and year=2010 and isSytem=false and userType=Manager and status=ACTIVE(即活跃用户)
  6. select * from user where organization=1 and year=2010 and createdBy='Sam' or 'Joe' [6] 是否需要不同的多列索引,由上述 3 列组成?

  7. 由于我们按照我最初的假设创建了一个多列索引,我可以安全地删除模型中当前定义的单个索引(idx_user_org_id、idx_user_year_id、idx_user_created_by)吗?

【问题讨论】:

  • EXPLAIN 是你最好的朋友

标签: mysql database jpa indexing


【解决方案1】:

您应该切换索引中列的顺序:

(organization, year, isSystem, userType, status, createdBy)

这使它可以更好地服务于这两个查询:

select * from user where organization=1 and year=2010 and isSystem=false and userType=Manager
select * from user where organization=1 and year=2010 and isSystem=false and userType=Employee

[6] 是否需要不同的多列索引,由上述 3 列组成?

它不需要需要新索引 - 它可以使用现有索引,但效率较低 - 只会使用前两列。不过,为此查询添加新索引似乎是个好主意。

我可以安全地删除单个索引

是的。您应该删除未使用的索引,否则它们只会占用磁盘空间并减慢表修改速度,而不会带来任何好处。

【讨论】:

  • 好的,至于 [6],如果我使用 (organization, year, createdBy) 创建多列索引,则将使用它来代替以前的索引。我说的对吗?
  • @user339108:可能它会使用那个索引,是的。您应该运行EXPLAIN SELECT ... 来确定。
  • 我尝试添加一个新的多列索引来解析 [6],之后所有查询似乎都在使用新的多列索引来处理 [1-5] 中提到的查询。但这似乎不正确?告诉我,我在这里缺少什么?
  • @user339108:有时两个索引之间的性能差异是如此之小以至于无关紧要,在这种情况下,MySQL 优化器可能会选择一个与您预期不同的索引。尝试使用第一个索引然后使用第二个索引对查询进行计时,看看是否有显着差异。如果没有,我不会太担心。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-19
  • 1970-01-01
  • 2017-06-13
  • 1970-01-01
  • 2012-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多