最近線上系統突然出現匯出資料超過 10 筆時,查詢逾時的狀況,在仔細查找之後。

發現了問題原因,透過應用端與數據端兩邊同時調整,將查詢的效率提昇了約數百倍以上

首先,原本應用端的商務邏輯為每一分頁筆數固定為10筆,所以使用者最多可以匯出 10 筆資料

而且原本的商務邏輯是寫成這樣的

            if (condition.LCKeys != null && condition.LCKeys.Count > 0)
{
sql += "AND (LTRIM(RTRIM(STR(T2.[LawNo],20,3)))+LTRIM(RTRIM(STR([LCNo],20,6)))) IN @LCKeys "; //問題點 (IN參數與欄位用了函數做處理)
dynamicParams.Add("@LCKeys", condition.LCKeys);
}

  

這段語法在 SQL Server 執行時,會轉換成以下的範例語法

(這裡 A 表 與 B表 為 1:N 關聯 )

SELECT LawNo,LCNo

FROM A INNER JOIN B

WHERE 1=1 AND LTRIM(RTRIM(STR(LawNo+LCNo))) IN (‘A1’,’A2’….’A10’)

在IN條件少的情況下,即使效率不好,還是可以進行資料匯出的

這次的問題是因為應用商務邏輯修改導致,從原本使用者最多只能匯出 10 筆資料

改為最多能匯出500筆資料.

從上述的範例可知 WHERE 條件式的 IN 參數就達 500 個

此外條件式欄位也因用了函數而走 Index Scan

在多個參數下,搜索時間自然拉長

來看看修改前的樣子

在上圖中測試語句只放了10個 IN 條件參數,可以見到執行效率整體不是挺好的

接下來看看我們如何做應用與數據端的調整

首先將應用端原本的查詢參數,改為 Table Valued Parameter 形式

並且將原本的 IN 查找語法,修改為與Table Valued Parameter 做  INNER JOIN

  var dynamicParams = new DynamicParameters();
var conditionSection = "";
DataTable dt = new DataTable();
dt.Columns.Add("LawNo");
dt.Columns.Add("LCNo"); for (int index = 0; index < condition.LCNos.Count; index++)
{
DataRow row = dt.NewRow();
row["LawNo"] = condition.LawNos[index];
row["LCNo"] = condition.LCNos[index];
dt.Rows.Add(row);
}
if (dt.Rows.Count > 0)
{
conditionSection = " INNER JOIN @LawsTempx X ON X.LawNo = T2.LawNo AND X.LCNo = T2.LCNo "; //加上額外的 INNER JOIN 條件
dynamicParams.Add("LawsTempx", dt.AsTableValuedParameter("LawsTemp")); //將DataTable轉換成TVP傳入數據庫
}

  

接下來在數據端需要建立一個對應的自訂 Table Type

最後來看看修改後的結果

可以看到整個修改完後,Logical read 數下降了快4萬之多,執行計畫也移掉了 Parallelism 執行

是不是感覺很簡單呢?這個用法不只能用在查找語句的改寫,也可以試著用在大量 Insert 緩慢的情境上

各位小夥伴,如果應用端突然出現這種情況的話,可以考慮看看與開發溝通,改用 TVP 進行改寫喲

謝謝大家

補充: 表值參數 (TVP) 的限制
https://docs.microsoft.com/zh-cn/sql/relational-databases/tables/use-table-valued-parameters-database-engine?view=sql-server-2017#Restrictions

有下面的限制:

  • SQL Server 不维护表值参数列的统计信息。

  • 表值参数必须作为输入 READONLY 参数传递到 Transact-SQL 例程。 不能在例程体中对表值参数执行诸如 UPDATE、DELETE 或 INSERT 这样的 DML 操作。

  • 不能将表值参数用作 SELECT INTO 或 INSERT EXEC 语句的目标。 表值参数可以在 SELECT INTO 的 FROM 子句中,也可以在 INSERT EXEC 字符串或存储过程中。

一次快速改寫 SQL Server 高效查詢的範例的更多相关文章

  1. 在 SQL Server 2012 附加 Adventure Works 範例資料庫

    原文地址:http://technet.microsoft.com/zh-tw/library/eb1f9417-4cca-4575-a725-187bcd60c7e7 附加数据库时报错 错误5123 ...

  2. 一次快速改写 SQL Server 高效查询的范例

    原文:一次快速改写 SQL Server 高效查询的范例 最近線上系統突然出現匯出資料超過 10 筆時,查詢逾時的狀況,在仔細查找之後. 發現了問題原因,透過應用端與數據端兩邊同時調整,將查詢的效率提 ...

  3. 如何将sqlserver的windows验证模式改为SQL Server 和 Windows 混合身份验证模式

    今天问同事拷贝了份虚拟机,里面已装好sqlserver2008,可是他装的时候选择的是windows身份验证,我需要将其改成SQL Server 和 Windows 混合身份验证模式,具体步骤如下: ...

  4. 转载:SQL Server高效 -- 设计(ITPUT 讨论汇总

    http://blog.csdn.net/zjcxc/article/details/8979756 认为在设计SQL Server对象时,主要会考虑哪些因素来避免出现性能问题? 讨论汇总——总体设计 ...

  5. 使用 FTP 迁移 SQL Server 数据_迁移数据_快速入门(SQL Server)_云数据库 RDS 版-阿里云

    背景信息 阿里云数据库 SQL Server 版导入数据有如下限制: 仅支持导入 SQL Server 2005.SQL Server 2008.SQL Server 2008R2 版本数据 仅支持全 ...

  6. SQL SERVER 变量的使用和样例

    定义和使用局部变量:说明: 局部变量是用户可自定义的变量. 作用范围仅在程序内部. 局部变量的名称是用户自定义的,命名的局部变量名要符合SQL Server 2000标识符命名规则=>以@开 在 ...

  7. 使用PD(Power Designer)设计数据库,并且生成可执行的SQL文件创建数据库(本文以SQL Server Management Studio软件执行为例)

    下载和安装PD: 分享我的软件资源,里面包含了对PD汉化包(链接出问题时可以留言,汉化包只能对软件里面部分菜单栏汉化) 链接:https://pan.baidu.com/s/1lNt1UGZhtDV8 ...

  8. sql server高效分页控件及c#调用实例

    第一.首先在sqlserver中创建一个存储过程 USE [BZY] GO /****** 对象: StoredProcedure [dbo].[up_ProcCustomPage2005_New] ...

  9. 【数据处理】SQL Server高效大数据量存储方案SqlBulkCopy

    要求将Excel数据,大批量的导入到数据库中,尽量少的访问数据库,高性能的对数据库进行存储. 一个比较好的解决方案,就是采用SqlBulkCopy来处理存储数据. SqlBulkCopy存储大批量的数 ...

随机推荐

  1. ionic3 懒加载在微信上缓存的问题

    1.懒加载是什么? 在ionic2中所有的组件.模块.服务.管道等都堆积在app.module.ts模块中,在页面初始化的时候会一次性加载所有的资源,导致资源过大,页面渲染缓慢,也导致app.modu ...

  2. HTML5仿微信聊天界面、微信朋友圈实例

    这几天使用H5开发了一个仿微信聊天前端界面,尤其微信底部编辑器那块处理的很好,使用HTML5来开发,虽说功能效果并没有微信那么全,但是也相当不错了,可以发送消息.表情,发送的消息自动回滚定位到底部,另 ...

  3. 第十四章——循环神经网络(Recurrent Neural Networks)(第二部分)

    本章共两部分,这是第二部分: 第十四章--循环神经网络(Recurrent Neural Networks)(第一部分) 第十四章--循环神经网络(Recurrent Neural Networks) ...

  4. SAP S4系统创建Customer和Vendor的BAPI

    对应的BAPI是:RFC_CVI_EI_INBOUND_MAIN SAP 又调皮了,又不安常理出牌!

  5. Linux的内存分页管理

    作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁转载 内存是计算机的主存储器.内存为进程开辟出进程空间,让进程在其中保存数据.我将从内存的物理特性出发,深入到内存 ...

  6. quillJS 富文本编辑器源码分析系列1

    quillJS 富文本编辑器目前是一款很火富文本编辑器,使用广泛,github 上面的 star 有 22,492,虽然说不以 star 论英雄,不过这可以说明它还是比较受欢迎的: 它的特点是:轻量, ...

  7. SSL,TLS

    今天突然收到邮件说SSL不能用了,基于SSL的HTTPS协议不通了,怎么办? java/android 的网络编程简直一窍不通,平时都是用到了问百度.只能恶补有关网络的知识了. 传输协议: 传输协议中 ...

  8. win10安装gitLab

    从控制面板选择hyper-V进行安装 1.打开控制面板选择程序=>选择启用或关闭windows功能=>选择Hyper-v 安装ubuntu 1.下载ubuntu系统(本次安装为18.04. ...

  9. 面向对象之三个基本特征(javaScript)

    1. 前言 2. 封装 3. 继承 4. 多态 5. 总结 1. 前言 了解过面向对象的同学应该都知道,面向对象三个基本特征是:封装.继承.多态,但是对于这三个词具体可能不太了解. 2. 封装 在说封 ...

  10. 用系统为centos6的主机,搭建PXE服务器,实现批量安装centos6,7系统

    1. iptables -F setenforce 0 临时关掉selinux,清掉防火墙 永久生效更改配置文件:vim /etc/sysconfig/selinux chkconfig iptabl ...