需要有关mysql索引和查询性能的基本建议

时间:2010-11-05 21:14:01

标签: sql mysql

在数据库设计方面,我是一个相对较新的人。我知道如何定义表,但随着数据库的增长,我开始遇到性能问题。有人可以给我一些关于如何使用mysql索引来提高查询性能的指导吗?我对索引的理解是它们阻止整个数据库表逐行搜索,同时仍然能够返回有效的结果。

我通常只为每个表定义一个主键,为每行提供唯一的ID。定义一个“索引”的想法是你为将在mysql语句的WHERE子句中使用的每个字段执行它吗?不确定这是否过于笼统。

举个例子,假设我们有以下三个表:

产品

products_id,products_name

类别

categories_id,categories_name

products_to_categories

products_id categories_id

我们要运行以下查询:

SELECT p.products_name, c.categories_name 
  FROM categories as c 
  JOIN products as p 
  JOIN products_to_categories as p2c 
 WHERE p.products_id=12345

我们会将products_to_categories表中的两个字段定义为索引,然后将products_id和categories_id定义为其父表中的主键吗?

非常感谢任何有关索引的一般方法的建议或指导!

5 个答案:

答案 0 :(得分:2)

  

我们会将products_to_categories表中的两个字段定义为索引,然后将products_id和categories_id定义为其父表中的主键吗?

是的,这正是我要做的。

此外,如果任何数据将是唯一的,例如产品名称,则可以为该列提供唯一键。这将使您的数据库引擎在找到唯一项目时停止搜索整个表。

这是您的查询优化:

SELECT p.products_name, c.categories_name 
  FROM categories as c
  LEFT JOIN products_to_categories as p2c ON p2c.categories_id = c.categories_id
  INNER JOIN products as p ON p.products_id = p2c.products_id
 WHERE p.products_id=12345

答案 1 :(得分:1)

考虑索引的最佳方式是您期望查询数据的方式。

假设数据库中的products_id和categories_id为PRIMARY KEY,这意味着它们会自动编入索引。如果没有,请从那开始。

当我做多连接表时,如果你想要偏执,创建两个索引以允许ID的双向可访问性,例如

CREATE TABLE products_to_categories (
    products_id integer unsigned NOT NULL,
    categories_id integer unsigned NOT NULL,
    INDEX p_to_c (products_id,categories_id),
    INDEX c_to_p (categories_id,products_id)
) ENGINE=MyISAM;

这需要很大的空间,但它会非常非常快,除非你查询两个方向(从产品到类别,然后反向),否则它可能有点过分。或者,默认情况下,我这样做:

CREATE TABLE products_to_categories (
    products_id integer unsigned NOT NULL,
    categories_id integer unsigned NOT NULL,
    INDEX p (products_id),
    INDEX c (categories_id)
) ENGINE=MyISAM;

如果您需要某种约束(多对一,一对多),则将索引类型更改为UNIQUE等。

通常,从后一个定义开始,执行查询,然后对其运行EXPLAIN。如果它显示匹配行数大于1的任何内容(第一个表除外),则重新处理索引。

数据库索引实际上更多的是测试和诊断问题,而不是许多人认为。我有一段时间不知道该怎么做,直到我确实遇到了问题。简而言之:

  1. 创建索引
  2. 确定您的查询
  3. 对您的查询运行EXPLAIN,并运行计时测试以确定查询速度!
  4. 调整索引
  5. 回到3
  6. 正如一位用户在下面评论过的那样,在运行计时测试之前,EXPLAIN是一个很好的起点,但没有什么比野外的实际计时测试更好。

答案 2 :(得分:0)

是,将products_to_categories表中的两个字段定义为索引,然后将products_id和categories_id定义为其父表中的主键。是的,定义索引背后的想法是你为将在mysql语句的WHERE子句中使用的每个字段执行此操作。

答案 3 :(得分:0)

为具有唯一约束的字段(包括主键)自动生成索引。但索引应该存在于两个表中的连接中使用的所有字段上。通常,使用explain <SQL>工具确切地找出正在使用的索引。当您要查找特定值时,请注意联接表的全表扫描。

答案 4 :(得分:0)

奇怪的是,到目前为止,大多数答案都没有在products_to_categories表中包含主键,因此可以插入重复项,例如。

insert into products_to_categories (prod_id, cat_id) values (1,1),(1,2),(1,1); -- oops

您可能需要查看我的以下答案,该答案针对按类别选择产品进行了优化,而无需二级索引。

Rewriting mysql select to reduce time and writing tmp to disk