将索引视为“目录”......这是指向文件中位置的指针的有序列表,也就是偏移量。假设您在表中存储了数百万条记录,而不是在表中搜索匹配条件,引用有序列表进行匹配要快得多,然后堆叠指向特定匹配行的指针。索引的一个完美示例是表的主键字段,最典型的是它的“id”字段。如果您想要行 id #11234566,向索引请求指向数据的指针比扫描数据源中的位置 11234566 要快得多。
这是索引的不那么明显的用法:
CREATE TABLE activity_log (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
activity_type_id SMALLINT UNSIGNED NOT NULL,
datetime_created DATETIME
KEY(activity_type_id),
PRIMARY KEY(id)
);
CREATE TABLE activity_log_to_date_key (
activity_log_id INT UNSIGNED NOT NULL,
date_created_key INT UNSIGNED NOT NULL REFERENCES dim_datetime(id),
UNIQUE KEY(activity_log_id),
KEY(date_created_key)
);
CREATE TABLE dim_datetime (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
date_hour DATETIME NOT NULL,
PRIMARY KEY(id),
KEY(date_hour)
);
SELECT a.activity_log_id, al.activity_type_id, al.datetime_created
FROM activity_log_to_date_key a
INNER JOIN dim_datetime d ON (d.id = a.date_created_key)
LEFT JOIN activity_log al ON (al.id = a.activity_log_id)
WHERE d.date_hour BETWEEN '2009-01-01 00:00:00' AND '2009-06-01 12:00:00';
将索引视为“目录”......这是指向文件中位置的指针的有序列表,也就是偏移量。假设您在表中存储了数百万条记录,而不是在表中搜索匹配条件,引用有序列表进行匹配要快得多,然后堆叠指向特定匹配行的指针。索引的一个完美示例是表的主键字段,最典型的是它的“id”字段。如果您想要行 id #11234566,向索引请求指向数据的指针比扫描数据源中的位置 11234566 要快得多。
这是索引的不那么明显的用法:
您的操作可以创建日志记录,然后创建对索引日期时间的引用,该引用比您的日志表搜索/排序更快。然后在它自己的主键上加入你的日志表。如果您需要我对此进行扩展,请告诉我。我希望这是有道理的。
示例查询:
很多人似乎错过的一点是,DBMS 通常(或只能)在查询中每个表引用只使用一个索引,如果它可以并且确实使用多个索引,那么使用组合索引可能会更快索引(如果存在)。
例如,如果在大表中搜索行,
WHERE AnIntegerColumn = 42 AND AnOtherInt = 69
那么到达这些行的最快路径将是 AnIntegerColumn 和 AnOtherInt 两列上的索引。如果您只有一个单独的索引但没有组合索引,则数据库将搜索一个或另一个索引并使用第二个子句单独过滤结果,或者扫描两者并随后将结果结合起来。另一个可以使用复合索引改进的常见简单操作是
WHERE SomeColumn = <SomeValue> ORDER BY SomeOtherColumn
- 如果 SomeColumn 和 SomeOtherColumn 上有索引(以正确的顺序),则在某些情况下可以同时执行过滤和排序操作。添加过多的索引当然可能是一个糟糕的优化,因为用于存储索引的额外空间(以及如果您的数据库看到许多写入操作时维护它们的 IO 负载)可能是比稍微不太优化的读取查询更糟糕的问题,所以不要过度。
大卫和兰迪对此进行了介绍。我只是想补充一点,该
EXPLAIN
命令可以极大地帮助您确定何时从创建索引中节省大量资金,以及建议需要哪些索引。它将显示数据库运行查询所采取的步骤,以便您知道哪些位花费的时间最长。我还没有看到这里提到的是,当您有多个磁盘时,您可能希望将索引放在与数据实际所在位置不同的磁盘上。这可以加快一些操作。我认为这本身就值得一个问题。