我有一个买方表Buyer,大概1万条记录;一个卖方表Sale,大概5万条记录。有一些买方和卖方之间是有某种关联的,这种关联关系被记录在Partner表里,Partner表中的关键字段包括BuyerID,SaleID和LinkManID,其中LinkManID是卖方的业务员之一。系统里还有一个联系人的概念,对于每一个买方,如果它和卖方在Partner表里有记录,就取Partner表中的LinkManID作为联系人ID;如果它和卖方在Partner表中无记录,那么需要去查找这个卖方的主业务员ID(每个卖方有1至n个业务员,其中有且仅有一个主业务员)来作为联系人ID。
   在程序中,经常涉及到查询和某买方有业务关系的卖方列表,里面都需要显示联系人信息。现在有两个方案:
(1)生成一个视图,视图里就三列:BuyerID,SaleID和LinkManID。视图很容易写,形成的视图在程序里用起来也很方便。但如果不加上查询条件,直接查询这个视图,会查出5五*1万=5亿条记录(卖方和买方表作笛卡尔积)。虽然我们实际用的时候,肯定会加上查询条件(不加查询条件是没有意义的),但似乎也存在忘加查询条件把服务器搞死的可能;另外,一个视图,只有给它加上查询条件才能使用,是不是也有点怪怪的?毕竟sqlserver不支持所谓带参视图。
(2)写一个函数,传入BuyerID和SaleID,以LinkManID为返回值。函数虽然好写,但放在查询语句里很别扭,用起来非常不舒服。
下面给出两个方案的伪代码:

 1--方案1 使用视图
 2SELECT     pa.BuyerID, pa.SaleID, us.UserName as LinkMan, us.Mobile, us.Phone
 3FROM         Buyer
 4    inner join Partner as pa on Buyer.UserID = pa.BuyerID and pa.IsBuyerFavorite=1
 5    inner join Sale on pa.SaleID = Sale.UserID
 6    inner join vLinkMan as lm on Buyer.UserID = lm.BuyerID and Sale.UserID = lm.SaleID
 7    inner join [user] as us on lm.LinkManID = us.UserID
 8
 9--方案2 使用函数
10SELECT a.*, us.UserName as LinkMan, us.Mobile, us.Phone FROM
11(
12    SELECT     pa.BuyerID, pa.SaleID, GetLinkManID(Buyer.UserID, Sale.UserID) as LinkManID
13    FROM         Buyer
14        inner join Partner as pa on Buyer.UserID = pa.BuyerID and pa.IsBuyerFavorite=1
15        inner join Sale on pa.SaleID = Sale.UserID
16) a 
17inner join [user] as us on a.LinkManID = us.UserID

在一开始,我个人比较偏向于方案1,因为正如伪代码中所显示的那样,使用视图更容易写查询语句,也更容易和其他的表进行关联;另外,从运行效率上,我对函数的运行效率深表怀疑,认为用视图更快。结果,当我试着在项目里把两种方案都试验了之后,吃了一惊,函数法的速度远远高于视图法。这时候我还不服气,忙着去给视图加索引,这时候才惊觉,由于我这个视图是使用外连接得到的(买方表和卖方表笛卡尔积),所以根本无法建立索引(如果这一点说错了请大家指正,在我建立索引的时候报错“无法在视图上创建 索引,因为该视图未绑定到架构”,百度了一下,发现视图中有外连接的话是不能建立索引的)。由于对视图的查询很慢,在sql server的查询计划里我们甚至可以看到它对要和视图进行连接的[user]表进行了lasy spool,而这个步骤又占去了查询的绝大多数时间:
 
而另一个让我以前没有想到的是,使用函数的效率竟然很高,下面是方案2的执行计划中标量计算所占的cpu百分比:

所以,最后自己还是采用了方案2,虽然用起来多了一层嵌套,但无论是安全性还是效率,都好于1。

两个sql设计方案的比较的更多相关文章

  1. 处于同一个域中的两台Sql server 实例无法连接

    处于同一个域中的两台Sql server 实例无法连接,报的错误信息如下: A network-related or instance-specific error occurred while es ...

  2. 处于同一域中的两台SQL Server 实例无法连接

    处于同一个域中的两台Sql server 实例无法连接,报的错误信息如下: A network-related or instance-specific error occurred while es ...

  3. 两道sql面试题

    两道sql面试题:    1. 数据库表A的数据如下:             year   quarter             2001      1             2001      ...

  4. 两个SQL查询,横向合并为一个查询结果

    第一条sql: select unit,count(*)as number from archives_management group by unit 第二条sql: select fine_uni ...

  5. spring boot集成mybatis只剩两个sql 并提示 Cannot obtain primary key information from the database, generated objects may be incomplete

    前言 spring boot集成mybatis时只生成两个sql, 搞了一个早上,终于找到原因了 找了很多办法都没有解决, 最后注意到生成sql的时候打印了一句话: Cannot obtain pri ...

  6. 两台SQL Server数据同步解决方案

    复制的概念 复制是将一组数据从一个数据源拷贝到多个数据源的技术,是将一份数据发布到多个存储站点上的有效方式.使用复制技术,用户可以将一份数据发布到多台服务器上,从而使不同的服务器用户都可以在权限的许可 ...

  7. (转载)按行合并两个sql的查询结果

    (转载)http://blog.csdn.net/wxwstrue/article/details/6784774 Union all join 是平行合并 为水平连接 Union all 是垂直合并 ...

  8. CASE WHEN 及 SELECT CASE WHEN的用法(写了一坨烂代码发现两条sql就行了, 哎)

    转自:http://blog.sina.com.cn/s/blog_4c538f6c01012mzt.html Case具有两种格式.简单Case函数和Case搜索函数. 简单Case函数 CASE  ...

  9. 比较两个Sql数据库是否相同

    1.打开VS20122.SQL→架构比较→新建架构比较3.在源和目标上分别填上两个待比较的数据库的信息4.点击比较,不一会儿,系统就会列出两个数据库的差异了.

随机推荐

  1. symfony安装总结

    将D:\ApacheServer\php路径添加到环境变量path中,在cmd命令行中可以执行php命令 打开php.ini 打开extension=php_openssl.dll file_put_ ...

  2. WCF 透明代理

    现在我们通过类似的原理创建一个用于模拟WCF服务端和客户端工作原理的模拟程序.[源代码从这里下载] 目录 一.基本的组件和执行流程 二.创建自定义HttpHandler实现对服务调用请求的处理 三.定 ...

  3. [C/C++] C++常见面试题

    参考:http://blog.csdn.net/shihui512/article/details/9092439 1.new.delete.malloc.free之间的关系 malloc和free都 ...

  4. 【bzoj3122】[Sdoi2013]随机数生成器 BSGS思想的利用

    题目描述 给出递推公式 $x_{i+1}=(ax_i+b)\mod p$ 中的 $p$.$a$.$b$.$x_1$ ,其中 $p$ 是质数.输入 $t$ ,求最小的 $n$ ,使得 $x_n=t$ . ...

  5. vb常用函数一览表

    常用内部函数 数学函数 函数 功能 示例 结果 说明 Abs(x) 绝对值 Abs(-50.3) 50.3   Exp(x) 自然指数 Exp(2) e^2 e(自然对数的底)的某次方 Fix(x) ...

  6. [Leetcode] Symmetric tree 对称二叉树

    Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For e ...

  7. POJ2774 Long Long Message 【后缀数组lcp】

    长长的消息 时间限制: 4000MS   内存限制: 131072K 提交总数: 32393   接受: 13079 案件时间限制: 1000MS 描述 小猫在拜特兰的首府物理专业.最近有一个不幸的消 ...

  8. win10 update orchestratorservere禁用

      1 Windows 10系统中有一项Update Orchestrator Service(更新协调器办事),在当地办事窗口中,我们发现 Update Orchestrator Service 办 ...

  9. MySQL使用笔记(五)简单数据记录查询

    By francis_hao    Dec 14,2016 查询指定字段 mysql> select field1,field2-- from table_name; 查询所有字段 mysql& ...

  10. Fragmenttabhost的使用教程

    1.准备tab的图标,放到mipmap目录下面,大小64x64,准备2种,一种是选中的,一种是未选中的,如下图 2.重写fragmentabhost,防止调用fragment每次点击tab都要重新调用 ...