如果在SELECT语句中连接两个表,则表列上的所有索引都不能再使用?

时间:2012-06-28 01:41:55

标签: sql indexing

假设我们有:

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

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

3 个答案:

答案 0 :(得分:3)

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

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

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

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

这并不是说您无法预测何时可以使用或不使用索引。但是,需要通过实践和经验来了解数据库可能执行查询的方式。

答案 1 :(得分:1)

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

此查询可能会返回多行数据。无论您想访问哪个表,任何一个表的索引都将非常有用。

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

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

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

答案 2 :(得分:0)

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

可能确保不能使用索引的东西是任何改变数据的函数/操作。 IE:从月份中获取月份/等,通配LIKE子句的左侧......