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万行
…有了这个推论,我们可以推断:
是一个ID匹配项,因此在大多数情况下,哈希索引会更好(PK集群问题除外,但我不会离题)Student.sID=Apply.sID
-这是一个范围搜索,因此在此处使用基于树的索引会有所帮助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