Sql server Apply需要使用散列或原始嵌套循环(每次扫描索引)进行连接。 Student上的索引意味着一个带有索引搜索的有效嵌套循环 Student.sID,Student.GPA 这是一个索引还是两个索引?如果是两个独立的索引,那么将使用第二个索引,而第一个索引显然是无用的申请和大学仍需要大量加入 Apply.cName,College.cName 这可能会在这两个列上获得一个合并联接,但是Student需要一个大联接 Apply.sID,Student.GPA 学生可以从1.5高效扫描,也可以寻找申请,但大学需要大量加入

Sql server Apply需要使用散列或原始嵌套循环(每次扫描索引)进行连接。 Student上的索引意味着一个带有索引搜索的有效嵌套循环 Student.sID,Student.GPA 这是一个索引还是两个索引?如果是两个独立的索引,那么将使用第二个索引,而第一个索引显然是无用的申请和大学仍需要大量加入 Apply.cName,College.cName 这可能会在这两个列上获得一个合并联接,但是Student需要一个大联接 Apply.sID,Student.GPA 学生可以从1.5高效扫描,也可以寻找申请,但大学需要大量加入,sql-server,indexing,hash,binary-search-tree,Sql Server,Indexing,Hash,Binary Search Tree,在这些选项中,第一个或最后一个可能更好,但如果没有进一步的信息,很难说 在实际系统中,我会在所有表上都有索引,并明智地使用INCLUDE列以避免键查找。您可能希望更好地了解哪些表需要提前筛选等。第一个问题 (请参见幻灯片7),也就是说,不能使用散列索引执行范围比较。这是因为(一般而言)散列函数是单向的:给定散列函数的输出,您无法确定输入,而输出显然是随机顺序的(具有随机顺序有助于确保在散列表容器集上均匀加载) 现在,举一个做作而过于简单的例子: 假设您有这些行: PK | Enrollment

在这些选项中,第一个或最后一个可能更好,但如果没有进一步的信息,很难说

在实际系统中,我会在所有表上都有索引,并明智地使用
INCLUDE
列以避免键查找。您可能希望更好地了解哪些表需要提前筛选等。

第一个问题 (请参见幻灯片7),也就是说,不能使用散列索引执行范围比较。这是因为(一般而言)散列函数是单向的:给定散列函数的输出,您无法确定输入,而输出显然是随机顺序的(具有随机顺序有助于确保在散列表容器集上均匀加载)

现在,举一个做作而过于简单的例子:

假设您有这些行:

PK | Enrollment
----------------
 1 |          1
 2 |         10
 3 |        100
 4 |       1000
 5 |      10000
此表的完美哈希索引如下所示:

假设
1
的哈希为
0xF822AA896F34253E
10
的哈希为
0xB383A8BBDAA41F98
,依此类推

EnrollmentHash     | PhysicalRowPointer
---------------------------------------
0xF822AA896F34253E |                  1
0xB383A8BBDAA41F98 |                  2
0xA60DCD4E78869C9C |                  3
0x49B0AF769E6B1EB3 |                  4
0x724FD1728666B90B |                  5
因此,给定此哈希表索引,查看哈希值时,您无法确定哪个哈希值代表较大的注册值,而不是较小的值。但是哈希表索引确实为您提供了单个特定值的
O(1)
查找,这就是为什么它最适合离散的、非连续的数据值,尤其是
JOIN
标准中使用的列

而树散列确实保留了有关值的相对顺序信息,但是使用了
O(logn)
lookup time

第二个问题 首先,我需要重写查询以使用现代
JOIN
语法。旧样式(使用逗号)自1992年SQL-92以来就已经过时了,那已经是近30年前的事了

SELECT
    *
FROM
    Apply
    INNER JOIN Student ON Student.sID = Apply.sID
    INNER JOIN College ON Apply.cName = Apply.cName
WHERE
    Student.GPA > 1.5
    AND
    College.cName < 'Cornell'
选择
*
从…起
申请
Student.sID=Apply.sID上的内部联接学生
在Apply.cName=Apply.cName上内部加入学院
哪里
学生平均成绩>1.5
及
College.cName<'康奈尔'
现在,一般来说,回答这类问题的最佳方法是了解表的
统计信息
(基数、值分布等)。但如果没有这些,我仍然可以做出一些猜测

我假设
College
是最小的表(~500行?),
Student
可能有1-200万行,假设每个学生都提出4-5个申请,那么
Apply
表将有~500万行

…有了这个推论,我们可以推断:

  • Student.sID=Apply.sID
    是一个ID匹配项,因此在大多数情况下,哈希索引会更好(PK集群问题除外,但我不会离题)
  • Student.GPA>1.5
    -这是一个范围搜索,因此在此处使用基于树的索引会有所帮助
  • College.cName
    -同样,这是一个范围比较,因此基于树的索引也有帮助
所以最好的索引应该是
Student.GPA
College.cName
,但这不是一个选项,所以让我们看看每个选项的好处是什么

(当我写这篇文章时,我看到@charlieface发布了他们的答案,这些答案已经涵盖了这一点,所以我将链接到他们的答案以节省我的时间:)

第一个问题 (请参见幻灯片7),也就是说,不能使用散列索引执行范围比较。这是因为(一般而言)散列函数是单向的:给定散列函数的输出,您无法确定输入,而输出显然是随机顺序的(具有随机顺序有助于确保在散列表容器集上均匀加载)

现在,举一个做作而过于简单的例子:

假设您有这些行:

PK | Enrollment
----------------
 1 |          1
 2 |         10
 3 |        100
 4 |       1000
 5 |      10000
此表的完美哈希索引如下所示:

假设
1
的哈希为
0xF822AA896F34253E
10
的哈希为
0xB383A8BBDAA41F98
,依此类推

EnrollmentHash     | PhysicalRowPointer
---------------------------------------
0xF822AA896F34253E |                  1
0xB383A8BBDAA41F98 |                  2
0xA60DCD4E78869C9C |                  3
0x49B0AF769E6B1EB3 |                  4
0x724FD1728666B90B |                  5
因此,给定此哈希表索引,查看哈希值时,您无法确定哪个哈希值代表较大的注册值,而不是较小的值。但是哈希表索引确实为您提供了单个特定值的
O(1)
查找,这就是为什么它最适合离散的、非连续的数据值,尤其是
JOIN
标准中使用的列

而树散列确实保留了有关值的相对顺序信息,但是使用了
O(logn)
lookup time

第二个问题 首先,我需要重写查询以使用现代
JOIN
语法。旧样式(使用逗号)自1992年SQL-92以来就已经过时了,那已经是近30年前的事了

SELECT
    *
FROM
    Apply
    INNER JOIN Student ON Student.sID = Apply.sID
    INNER JOIN College ON Apply.cName = Apply.cName
WHERE
    Student.GPA > 1.5
    AND
    College.cName < 'Cornell'
选择
*
从…起
申请
Student.sID=Apply.sID上的内部联接学生
在Apply.cName=Apply.cName上内部加入学院
哪里
学生平均成绩>1.5
及
College.cName<'康奈尔'
现在,一般来说,回答这类问题的最佳方法是了解表的
统计信息
(基数、值分布等)。但如果没有这些,我仍然可以做出一些猜测

我假设
College
是最小的表(~500行?),
Student