Xav*_*nou 4 sql t-sql sql-server performance
我有一些性能问题.
我有一张大约200万行的表.
CREATE TABLE [dbo].[M8](
[M8_ID] [int] IDENTITY(1,1) NOT NULL,
[APPLIC] [char](8) NOT NULL,
[NIVALERTE] [numeric](1, 0) NOT NULL,
[LOGDH] [datetime2](7) NULL,
[USERX] [char](20) NOT NULL,
[TACHE] [char](3) NOT NULL,
[PRG] [char](32) NOT NULL,
[DOS] [numeric](3, 0) NOT NULL,
[ERRNUM] [numeric](5, 0) NOT NULL,
[LOGTXT] [char](200) NOT NULL)
Run Code Online (Sandbox Code Playgroud)
我用C#和ADO.NET阅读它们
在管理工作室(SQL Server 2008 R2)中,使用该查询:
SELECT
M8.M8_ID, M8.APPLIC, M8.NIVALERTE, M8.LOGDH, M8.USERX, M8.TACHE,
M8.PRG, M8.DOS, M8.ERRNUM, M8.LOGTXT
FROM
M8 AS M8 WITH(NOLOCK)
WHERE
((M8.APPLIC LIKE 'DAV' ) )
ORDER BY
M8.LOGDH DESC, M8.M8_ID ASC
OPTION (FAST 1)
Run Code Online (Sandbox Code Playgroud)
拥有第一行大约需要1分钟.
但是,随着
DECLARE @APPLIC_ZOOMAPRESCLE_ZOOM_LIKE_APPLIC_WHERE_0 as char(8) = 'DAV'
SELECT
M8.M8_ID, M8.APPLIC, M8.NIVALERTE, M8.LOGDH, M8.USERX, M8.TACHE,
M8.PRG, M8.DOS, M8.ERRNUM, M8.LOGTXT
FROM
M8 AS M8 WITH(NOLOCK)
WHERE
((M8.APPLIC LIKE @APPLIC_ZOOMAPRESCLE_ZOOM_LIKE_APPLIC_WHERE_0 ) )
ORDER BY
M8.LOGDH DESC, M8.M8_ID ASC
OPTION(FAST 1)
Run Code Online (Sandbox Code Playgroud)
我在4秒后得到第一行.
PS:我知道,我没有%.
编辑:以下是执行计划https://www.dropbox.com/sh/jgai5f9txbs84x6/EP5_hj8DNv
你的桌子有1,517,820行.其中近三分之一(476,672)包含该值DAV(或者更准确地说DAV?????是CHAR(8)数据类型的值,因此用尾随空格填充.
在LIKE比较中,尾随空格match_expression并不重要(尽管它们pattern本身很重要).
因此,表达式WHERE APPLIC LIKE 'DAV'确实匹配476,672行.然而,这两个执行计划都没有估计到这附近.虽然更快的计划(带变量)更接近三个数量级.
+-----------------------+-----------+-----------+
| | Slow Plan | Fast Plan |
+-----------------------+-----------+-----------+
| Estimated # Rows | 32 | 47,343 |
| Memory Grant | 1 MB | 333 MB |
| Degree of Parallelism | 1 | 4 |
+-----------------------+-----------+-----------+
Run Code Online (Sandbox Code Playgroud)
对于带有变量的计划,因为SQL Server没有进行变量嗅探(没有例如OPTION (RECOMPILE)提示),它会回到关于有多少行与谓词匹配的猜测,并得出估计约有3.1%的表符合条件.

具有字面值的计划应该有更好的估计.您提供的DBCC SHOW_STATISTICS输出屏幕截图(在添加了另外一百万行之后)显示DAV肯定在那里

不幸的是,尽管列值中的尾随空格对于查询结果并不重要,但它们的存在确实搞乱了基数估计(在此处报告为错误并且当前声明在下一版本中已修复).由于这个问题,它估计只返回少量行,并提出以下计划.

由于基数估计不佳而导致执行50万次密钥查找,因此内存授权可能不足以满足正在排序的数据大小导致溢出tempdb.
如果可以更改查询或表模式,则可以考虑许多解决方法.
=而不是LIKEWHERE子句更改为LIKE CAST('DAV' AS CHAR(8))VARCHAR(8)(并确保修剪所有存储的值).Index_A).您尚未提供其定义,但如果它是具有少量不同值的列上的单列索引,则其存在可能更多是障碍而不是帮助(取决于您的查询工作负载))APPLIC(可能LOGDH DESC, M8_ID ASC避免排序),将其他引用的列添加为INCLUDED.| 归档时间: |
|
| 查看次数: |
297 次 |
| 最近记录: |