0

我意识到,在为用于“ORDER BY”的列创建索引时,对 MySQL 查询的响应会变得更快,例如

SELECT username FROM table ORDER BY registration_date DESC

现在我想知道我应该创建哪些索引来优化请求时间。例如,我经常使用以下查询:

SELECT username FROM table WHERE
    registration_date > ".(time() - 10000)."

SELECT username FROM table WHERE
    registration_date > ".(time() - 10000)."
    && status='active'

SELECT username FROM table WHERE
    status='active'

SELECT username FROM table ORDER BY registration_date DESC

SELECT username FROM table WHERE
    registration_date > ".(time() - 10000)."
    && status='active'
    ORDER BY birth_date DESC

问题 1: 我应该为前三种请求类型设置单独的索引吗?(即“registration_date”列的一个索引,“status”列的一个索引,以及两者组合的另一个列?)

问题 2: “WHERE”和“ORDER BY”是否独立使用不同的索引?比如说,我有一个“status”和“registration_date”列的组合索引,还有一个“birth_date”列的索引。我应该为三列(“status”、“registration_date”和“birth_date”)设置另一个组合索引吗?

4

5 回答 5

3

索引或查询优化没有硬性规定。每个案例都需要考虑和审查。

但是,一般来说,您可以并且应该为经常排序或在 WHERE 语句中使用的列添加索引。(对问题 2 的回答——不,相同的索引可能用于ORDER BYWHERE)是否执行多列索引或单列索引取决于查询的频率。此外,您应该注意单列索引可以由 mySQL 使用索引合并优化组合:

Index Merge 方法用于检索具有多个范围扫描的行并将其结果合并为一个。合并可以生成其底层扫描的并集、​​交集或交集并集。此访问方法合并来自单个表的索引扫描;它不会跨多个表合并扫描。

(更多阅读:http ://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html )

多列索引还要求您注意构建查询,以使您对索引列的使用与索引中的列顺序相匹配:

如果列不构成索引的最左前缀,则 MySQL 不能使用索引。假设您有此处显示的 SELECT 语句:

SELECT * FROM tbl_name WHERE col1=val1; SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;

SELECT * FROM tbl_name WHERE col2=val2; SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;

如果 (col1, col2, col3) 上存在索引,则只有前两个查询使用该索引。第三和第四个查询确实涉及索引列,但是 (col2) 和 (col2, col3) 不是 (col1, col2, col3) 的最左边的前缀。

请记住,索引确实有自己的性能考虑 - 可以“过度索引”表。每次插入记录或修改索引列时,都必须重建索引/索引。这确实需要资源,并且根据表的大小和结构,它可能会在索引构建操作处于活动状态时导致响应能力下降。

用于EXPLAIN准确找出查询中发生的情况。分析,实验,不要过度。霰弹枪方法不适用于数据库优化。

文档

于 2012-07-27T15:34:10.267 回答
1

引用此页面

[索引] 会减慢您的更新和插入速度。

这就是你必须计算的权衡。要优化您的表,您应该将索引放在您最有可能应用条件的列中 - 您拥有的索引越多,您的数据更改操作就越慢。从这个意义上说,我个人认为创建组合索引没有多大好处 - 如果您为 3 列创建所有 7 种可能的索引排列,那么您肯定会在更新和插入上施加更多阻力,而不仅仅是为 3 列使用 3 个索引(甚至这也值得商榷)。另一方面,如果数据的编辑量比编辑量大得多SELECT,那么索引确实可以帮助您加快处理速度。

其他需要考虑的事情(再次引用上面的页面):

如果您的表非常小[...],使用索引比将其排除在外并让它进行表扫描更糟糕。索引实际上只在具有大量行的表中派上用场。

于 2012-07-27T15:30:40.977 回答
1

是的,在您经常使用的列上设置索引是个好主意,无论是在 order by 还是在 where 子句中。

但请注意:如果您有索引,UPDATES、INSERTS 和 DELETE 会减慢速度。

那是因为在这样的操作之后,索引也必须更新。

因此,作为一个经验法则:如果您的应用程序是读取密集型的,请使用您认为有帮助的索引。

如果您的应用程序经常更新数据,请小心,因为索引可能会变慢。

如有疑问,您必须弄脏手,并研究 EXPLAIN 的结果。

http://dev.mysql.com/doc/refman/5.6/en/explain.html

于 2012-07-27T15:30:41.613 回答
1

对于前两个示例,您可以通过一个索引来满足它们:{registration_date, status}。这样的索引可以支持对第一项 (registration_date) 或两者的过滤器。

但是,它并不能单独用于状态。关于地位的问题是地位的选择性。也就是说,有多少比例的记录具有状态=“活动”。如果这个比例很高(因此,平均而言,每个数据库页面都会有一条活动记录),那么索引可能没有多大帮助。

订单比较棘手。我不知道mysql是否为此目的使用索引。通常,使用索引对整个记录进行排序的效率低于仅对记录进行排序。使用索引会导致对页面中记录的随机访问模式,这可能会导致大于页面缓存的表出现重大性能问题。

于 2012-07-27T15:31:08.057 回答
0

在您的 select 语句中使用 explain 函数来确定您的连接在哪里减慢(引用的行越多,速度越慢)。然后将您的索引应用于这些列。

EXPLAIN SELECT * FROM table JOIN table 2 ON a = b WHERE conditions;
于 2012-07-27T15:24:40.883 回答