Rob*_*Rob 6 mysql database indexing database-design
我最近一直在考虑我的数据库索引,过去我只是非常挑衅地把它们作为事后的想法投入,并且如果它们是正确的甚至是帮助的话,从来没有真正考虑过.我读过相互矛盾的信息,有人说更多的索引更好,而其他索引也不好,所以我希望得到一些澄清,并在这里学到一点.
假设我有这个假设的表格:
CREATE TABLE widgets (
widget_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
widget_name VARCHAR(50) NOT NULL,
widget_part_number VARCHAR(20) NOT NULL,
widget_price FLOAT NOT NULL,
widget_description TEXT NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
我通常会为将要连接的字段和最常排序的字段添加索引:
ALTER TABLE widgets ADD INDEX widget_name_index(widget_name);
Run Code Online (Sandbox Code Playgroud)
现在,在一个查询中,例如:
SELECT w.* FROM widgets AS w ORDER BY w.widget_name ASC
Run Code Online (Sandbox Code Playgroud)
本widget_name_index是用来排序的结果集.
现在,如果我添加搜索参数:
SELECT w.* FROM widgets AS w
WHERE w.widget_price > 100.00
ORDER BY w.widget_name ASC
Run Code Online (Sandbox Code Playgroud)
我想我需要一个新的索引.
ALTER TABLE widgets ADD INDEX widget_price_index(widget_price);
Run Code Online (Sandbox Code Playgroud)
但是,它会使用两个索引吗?据我了解,它不会......
ALTER TABLE widgets ADD INDEX widget_price_name_index(widget_price, widget_name);
Run Code Online (Sandbox Code Playgroud)
现在widget_price_name_index将用于选择和订购记录.但是,如果我想转过头来做这件事怎么办:
SELECT w.* FROM widgets AS w
WHERE w.widget_name LIKE '%foobar%'
ORDER BY w.widget_price ASC
Run Code Online (Sandbox Code Playgroud)
将widget_price_name_index用于此?或者我widget_name_price_index也需要一个吗?
ALTER TABLE widgets ADD INDEX widget_name_price_index(widget_name, widget_price);
Run Code Online (Sandbox Code Playgroud)
现在,如果我有一个搜索的搜索框widget_name,widget_part_number和widget_description?
ALTER TABLE widgets
ADD INDEX widget_search(widget_name, widget_part_number, widget_description);
Run Code Online (Sandbox Code Playgroud)
如果最终用户可以按任何列排序怎么办?我很容易看到如何只用5列就能得到十几个索引.
如果我们添加另一个表:
CREATE TABLE specials (
special_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
widget_id INT UNSIGNED NOT NULL,
special_title VARCHAR(100) NOT NULL,
special_discount FLOAT NOT NULL,
special_date DATE NOT NULL
);
ALTER TABLE specials ADD INDEX specials_widget_id_index(widget_id);
ALTER TABLE specials ADD INDEX special_title_index(special_title);
SELECT w.widget_name, s.special_title
FROM widgets AS w
INNER JOIN specials AS s ON w.widget_id=s.widget_id
ORDER BY w.widget_name ASC, s.special_title ASC
Run Code Online (Sandbox Code Playgroud)
我假设这将使用widget_id_index和连接的widgets.widget_id主键索引,但排序呢?这将同时使用widget_name_index和special_title_index?
我不想长时间徘徊,我可以想到无数的场景.显然,对于真实场景而言,这可能会变得更加复杂,而不是几个简单的表格.任何澄清将不胜感激.
通过最佳实践,您无需在定义表示意图时创建索引.在应用程序中创建查询时,最好创建索引.在大多数情况下,您将从单列索引开始以满足查询.如果要在查询中使用多个列,可以创建覆盖索引.
覆盖索引是其中包含两列或更多列的索引.如果索引满足查询的所有列要求,则存储引擎可以从索引获取所有结果,而不是在磁盘I/O操作中踢.因此,在创建使用更多列的查询时,您可以创建覆盖所有必需列的新索引,也可以扩展现有索引以包含更多列.
在执行上述任何一项操作时,您必须考虑一些因素.只有当索引的最左列可以在查询中使用时,MySQL才会考虑索引.否则,它只是寻找整个表来获取结果.因此,如果您可以扩展现有索引而不影响使用该索引的所有查询,那么这将是明智的选择.否则,您可以继续为新查询创建新索引.有时,可以调整查询以适应索引结构.
| 归档时间: |
|
| 查看次数: |
269 次 |
| 最近记录: |