在数据库设计方面,我是一个相对较新的人。我知道如何定义表,但随着数据库的增长,我开始遇到性能问题。有人可以给我一些关于如何使用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定义为其父表中的主键吗?
非常感谢任何有关索引的一般方法的建议或指导!
答案 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的任何内容(第一个表除外),则重新处理索引。
数据库索引实际上更多的是测试和诊断问题,而不是许多人认为。我有一段时间不知道该怎么做,直到我确实遇到了问题。简而言之:
正如一位用户在下面评论过的那样,在运行计时测试之前,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