0

假设我们有:

  SELECT * 
    FROM Pictures 
    JOIN Categories ON Categories.CategoryId = Pictures.CategoryId
   WHERE Pictures.UserId = @UserId
ORDER BY Pictures.UploadDate DESC

在这种情况下,数据库首先连接两个表,然后在派生表上工作,我认为这意味着单个表上的索引将没有用,除非您能想出一个绑定到某个列的索引派生表?

4

3 回答 3

3

您对 SQL 的工作原理有一个根本性的误解。SQL 语言指定应返回的结果集。它没有说明数据库应该如何实现这些结果。

由数据库引擎来解析语句并提出一个执行计划(希望是一个有效的计划)来产生正确的结果。许多现代关系数据库都有复杂的查询优化器,可以完全分离语句并派生似乎与原始查询没有关系的执行计划。(至少对未经训练的人来说不是)

如果引擎使用基于成本的优化器,同一查询的执行计划甚至会随着时间而改变。基于成本的优化器根据已收集的有关数据和索引的统计信息做出决策。随着统计数据的变化,执行计划也会发生变化。

通过您的简单查询,您假设数据库必须在应用 where 子句之前连接表并创建一个临时结果集。这可能是您对问题的看法,但数据库可以自由地以完全不同的方式实现它。我怀疑有很多(如果有的话)数据库会为您的简单查询创建临时结果集。

这并不是说您永远无法预测何时可以使用或不使用索引。但是需要实践和经验才能了解数据库如何执行查询。

于 2012-06-28T03:26:19.543 回答
1

如果图片的“CategoryId”在表“Categories”的 CategoryId 字段中,这将加入为您提供所有类别信息的表。(如果没有此类类别,则没有特定“图片”的结果)

此查询可能会返回几行数据。无论您要访问哪个表,任一表的索引都会很有用。

通常你的程序会循环遍历结果集。

CategoryId 将为您提供具有该类别中所有相关字段的类别中的行,并且“Picture.Id”(假设有这样一个字段)将为您提供对数据库中该确切图片行的引用。

然后,您可以使用相关索引“UPDATE Categories SET .... WHERE CategoryId =” + “UPDATE Pictures ..... WHERE PictureId =" + 或某些类似的索引来操作任一表,具体取决于您的编程环境。

于 2012-06-28T02:12:38.657 回答
0

索引由优化器使用,这取决于查询中发生的情况。对于发布的查询,没有什么可以阻止索引被使用。但是,并非所有数据库的操作都相同——MySQL 只允许每个 SELECT 使用一个索引(检查查询计划,因为优化器可能会解释 JOIN 以便可以使用另一个索引)。

可能确保无法使用索引的东西是改变数据的任何功能/操作。IE:让月份/等日期过期,在 LIKE 子句的左侧通配符......

于 2012-06-28T01:48:51.140 回答