想要让你的SQL Server数据库飞一般的快?这5个优化技巧不能错过!

唉,总结太形式化了,就像写考试答案一样……我自己遇到的一个陷阱是,光看理论没有帮助,需要结合现实场景。
上周,一位客户问我为什么我的电子商务系统查询很慢。
查看数据库,索引乱七八糟,还有一些视图根本没有被使用。
无法直接修复它。

说真的,请优化一下。
必须尝试。
想一想。

1 .索引不仅仅是添加的。
上次我们在上海的一个购物中心举办活动时,我们的客户数据突然增加了一倍。
原本添加到User ID的索引突然变慢了。
后来我发现我需要添加一个封面索引来解决这个问题。
您需要知道何时使用聚集索引、非聚集索引或复合索引。
碎片处理也根据情况而有所不同。
根据数据量的不同,重建索引可能不如重组那么快。
“碎片率大于3 0%时建议重建”的说法是基于经验,但具体情况会根据业务场景而有所不同。

2 视图很容易陷入麻烦。
我之前有一个项目。
三层视图嵌套,让报表更加美观。
结果导入数据花了半天时间。
SQL Server 没有具体化视图。
我需要使用索引视图,上次尝试时,我将WISCHEMABINDING索引视图添加到报告系统中。
结果我一改表结构就崩了。
实在是让我很头疼。
你提到的“数据量稳定、查询频率高”的条件太理想了。
真的,谁能保证数据永远稳定呢?
3 我们都知道存储过程和参数化查询,但上次我们创建新的手写存储过程时,参数的使用方式令人困惑,并且是硬编码的。
因此,无法再处理 S​​QL 注入。
WITHRECOMPILE 非常有用,特别是在参数频繁变化的场景下,但使用过多会消耗大量内存,所以必须权衡一下。
关于错误处理,建议在写TRY...CATCH的时候,也记录一下,而不是只写ROLLBACK。
否则,一旦出现问题,你就会毫无头绪。

4 当谈到内存管理时,MaxServerMemory 参数非常重要。
我有一个客户,服务器大小是1 6 G。
他强制MaxServerMemory为1 2 G。
结果,系统停止工作。
我检查发现SQL Server占用了9 G,导致系统速度变慢。
最小服务器内存也会得分。
如果设置得太低,数据库将承受重负载并耗尽内存。
LockMemory在高并发场景下应该进行调优,但是调太多会让CPU紧张,所以需要找到一个平衡点。

5 性能分析工具SQLServerProfiler很直观,但是我上次在客户端打开一个小时,CPU使用率就到了2 00%。
然后我切换到 XEvents,它确实轻量得多。
DTA 非常有用,但上次我用它为客户生成推荐时,它推荐了 1 0 个索引,而我手动删除了 7 个。
您认为这准确吗?您需要能够读取 DMV,例如 sys.dm_exec_query_stats。
每晚运行你的脚本,看看谁消耗了最多的资源,这样你就不会在第二天被老板责骂。

6 .高级优化。
建议初学者不要接触分区表。
上次我们团队做分区表的时候,分区键选错了,数据来回删了半个多月。
尽可能避免使用查询提示。
上次我使用 OPTION(MAXDOP4 ) 时,内存溢出。
我真的惊呆了。
列存储索引?算了,我客户建了一个数据仓库,运维团队说硬盘都快满了。
数据压缩速度很快,但空间不够。

无论如何,这取决于你。
无论这个理论多么吸引人,最好去客户站点,运行缓慢的查询,然后逐步尝试。
有时您可以通过添加索引来解决问题,但有时您可能需要更改存储过程或重新设计表结构。
我还在思考这个问题。
如何使所有这些优化技术成为日常维护的一部分,而不是每次出现问题时即兴发挥......

聊聊mysql索引的最左前缀原则

最左边的前缀规则使用索引顺序中最左边的列。
例如,idx(a,b,c),WHERE a=1 使用索引,WHERE a=1 AND b=2 也使用它。
如果 WHERE 没有使用正确的列,索引将毫无用处。

我上周刚刚进行了一个查询,其中 c=3 根本不使用 idx(a,b,c) 。
直接读取整个表是非常慢的。

创建索引时,不要盲目添加列。
按照问题的顺序,左栏是最重要的。
想一想,如果单独检查KU b=2 的话,索引就没啥用了。

HAVING 过滤聚合结果,而不是原始数据。
如果你像这样输入 WHERE 来过滤数据,并且必须再次过滤,那么索引将毫无用处。

我通常不建议混合 WHERE 并且你应该做同样的事情。
只需直接输入 WHERE 即可。

这是第一个。

mysql索引命中规则讲解

索引首先匹配最左边的列。
(A,B,C) 索引,A=1 AND B=2 AND C=3 可以击中所有人。
范围查询破坏连续性,B>2 C不能使用索引(A,B,C)。
最左边的列 B=2 AND C=3 丢失,无法到达索引 (A,B,C)。

聚集索引留下归档数据,一次IO检查主键。
非聚集索引让它存储键值,需要一次IO返回表。
B+树的高度取决于列长度和块大小,分支缓存的I/O较少。

WHERE分为三个过滤类别: IndexFirstKey定位起始范围,第一次判断。
IndexLastKey定位最终范围并对每条记录进行判断。
IndexFilter 过滤掉索引中不符合要求的记录。
TableFilter 过滤表中的完整记录。

结果索引:最左边的匹配定位B+树的叶子并快速检索数据。
缺失索引:全表扫描,逐行检查所有条件。

示例 (A,B) 索引,A=1 AND B>2 : 分解:A=1 (FirstKey), B>2 (LastKey+Filter)。
放置:在B+树的A列中找到值为1 的起始节点,直到A=1 扫描:从起始节点读取B>2 条记录,继续判断B值。
返回表:非索引列应返回表,然后通过TableFilter进行过滤。

优化:高频条件放在左侧,范围列放在右侧。
避免函数计算,否则索引将不再有效。
联合索引列不宜过多,以减少表的维护和恢复。