sql(sqlserver) join 的表是否必须有主键?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql(sqlserver) join 的表是否必须有主键?相关的知识,希望对你有一定的参考价值。

这个不是必须的。

比如,ID是主键,在sql语句中,用name连接,是没有错误的。
参考技术A 这个可以没有
A join B on a.Id=B.Id 如果在表连接条件的字段中增加主键索引,可以加快查询速度本回答被提问者采纳

SqlServer2008R2执行计划

1.执行计划

执行计划的生成过程如下图:

SqlServer2008R2执行计划_sql

(1).分析过程

这三个比较容易理解,首先我们要保证sql的语法不能错误,select和join的表是必须存在的,以及你是有执行这个sql的权限,这样我们就走完了执行计划生命周期的第一个流程。

(2).编译过程

保证了上面sql这三点的话,引擎就必须硬着头皮看你这么一大坨烂sql,该删的删,该改的改,该转换的转换,比如说你的“子查询”会转化为“表连接”等等。。。其实也挺难为引擎的,举个例子:

子查询生成的sql:

SqlServer2008R2执行计划_缓存_02

join生成的sql:

SqlServer2008R2执行计划_缓存_03

从上面的两个结果中,你可以看到,大家都是玩join的,如果你仔细看的话,会发现一个是“哈希匹配”,一个是“嵌套循环”,为什么不一样,这 当然是引擎根据很多情况综合评选出来的,比如说:磁盘IO,逻辑读,资源占用,硬件环境等等。。。这也是所谓的“计划选优”操作。

(3).执行过程

既然执行计划都选出来了,理所当然就要执行了,执行完后会把sql和执行计划放入缓存,这样下次有同样的sql过来的时候就可以直接从Cache中提取了,不需要再次生成计划了,你也看到,生成执行计划还是比较消耗CPU时间的。

2.sql和执行的计划的缓存

刚才也说了,sql和plan都已经放入缓存了,那我的好奇心比较强,我就想看看sql和plan到底在哪,并且长的是个什么丑样子,刚好sqlserver还是比较能够满足我们G点的。

(1).为了方便查看缓存,我需要先将所有的缓存清空,比如下面的语句。
DBCC freeproccache
SELECT c.*
FROM dbo.Category AS c
JOIN dbo.Product AS p
ON c.CategoryId = p.CategoryId
WHERE c.CategoryId = 23794;
(2).通过sys.dm_exec_cached_plans拿到sql和plan的指针(plan_handle),如下图
SELECT * FROM sys.dm_exec_cached_plans;

SqlServer2008R2执行计划_执行计划_04

从图中你看到了两个adhoc(即时查询),分别是我在第一步执行的join查询和我在第二步执行的这个select。

(3).现在我们已经拿到了2个adhoc的plan_handle,然后通过dm_exec_sql_text查看他们的sql分别是怎样?

SqlServer2008R2执行计划_缓存_05

(4).看完text缓存,接下来我们继续看看sql的plan缓存在哪?可以通过dm_exec_query_plan来查看。

SqlServer2008R2执行计划_sql_06

以上是关于sql(sqlserver) join 的表是否必须有主键?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server nested loop join 效率试验

SQL Server:CROSS JOIN 和 FULL OUTER JOIN 有啥区别?

SQL中的join操作总结(非常好)

SQL Server JOINS:SQL Server 中是不是默认关联“JOIN”语句“LEFT OUTER”? [复制]

SQL Server:最好使用 varchar(MAX) 还是保留一个单独的注释表和 INNER JOIN 呢?

SQL Server 中的表、行值 UDF