-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathexecution_plan_audit.py
More file actions
2197 lines (1739 loc) · 109 KB
/
execution_plan_audit.py
File metadata and controls
2197 lines (1739 loc) · 109 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import pyodbc
import xml.etree.ElementTree as ET
import sqlparse
def get_execution_plan(conn, query):
"""
获取SQL查询的执行计划。
"""
# 使用 "SET SHOWPLAN_XML ON" 命令获取XML格式的执行计划
set_showplan_cmd = "SET SHOWPLAN_XML ON;"
cursor = conn.cursor()
cursor.execute(set_showplan_cmd)
# 将查询的SELECT部分替换为SELECT TOP 0
modified_query = query.replace("SELECT", "SELECT TOP 0", 1)
try:
cursor.execute(modified_query)
except pyodbc.Error as e:
print(f"错误: {e}")
if "列名" in str(e) or "无效" in str(e) or "语法" in str(e):
print("提示:请检查SQL语句的语法、表结构和列名。")
else:
print("提示:可能是权限问题或其他数据库配置问题。")
return None
# 获取执行计划
plan = cursor.fetchone()[0]
cursor.close()
# 在获取计划后重置SHOWPLAN_XML为OFF
set_showplan_off_cmd = "SET SHOWPLAN_XML OFF;"
cursor = conn.cursor()
cursor.execute(set_showplan_off_cmd)
cursor.close()
return plan
def audit_execution_plan(plan_xml):
"""
审计获取的执行计划,并返回任何潜在的性能问题。
"""
try:
root = ET.fromstring(plan_xml)
except Exception as e:
print(f"解析执行计划时出错: {e}")
return
''''
已校验规则1,4,5,6,103,168,225,231,254,255,256,304,308,315,318,319,329
复合规则10,
'''
print("开始进行执行计划审计...")
# 规则 1: 检查全表扫描 √
table_scans = root.findall(".//*[@PhysicalOp='Table Scan']")
if table_scans:
print("警告: 查询中存在全表扫描,可能影响性能。")
# 规则 2: 检查缺失的索引
missing_indexes = root.findall(".//MissingIndex")
if missing_indexes:
print("提示: 查询可能受益于添加以下索引:")
for index in missing_indexes:
columns = ', '.join([col.get('Name') for col in index.findall(".//ColumnGroup/Column")])
print(f"表: {index.get('Table')} - 列: {columns}")
# 规则 3: 检查预估的行数与实际行数的偏差
rel_ops = root.findall(".//RelOp")
discrepancies = [ro for ro in rel_ops if float(ro.get('EstimateRows', '0')) != float(ro.get('ActualRows', '0'))]
if discrepancies:
print("警告: 预估的行数与实际行数有较大偏差,可能需要更新统计信息。")
# 规则 4: 检查并行查询 √
parallel_queries = [element for element in root.iter() if
element.tag.endswith('RelOp') and element.get('Parallel') == '1']
if parallel_queries:
print("警告: 查询并行执行,可能导致资源争用。")
# 规则 5: 检查排序操作 √
sort_ops = root.findall(".//*[@PhysicalOp='Sort']")
if sort_ops:
print("警告: 查询中存在Sort操作,可能意味着查询正在对数据进行排序。考虑优化排序策略或使用索引。")
# 规则 6: 检查哈希匹配 √
# 注意: 在 SQL Server 的 XML 执行计划中,哈希匹配可能被表示为 PhysicalOp 属性值为 'Hash Match' 的元素
hash_matches = root.findall(".//*[@PhysicalOp='Hash Match']")
if hash_matches:
print("警告: 查询中存在哈希匹配,可能需要大量内存。这可能表示没有找到合适的索引。考虑优化查询或添加合适的索引。")
# 规则 7: 检查昂贵的操作
high_cost_ops = root.findall(".//RelOp[@EstimatedTotalSubtreeCost>10]")
if high_cost_ops:
print("警告: 查询中存在昂贵的操作,考虑优化查询。")
# 规则 8: 检查子查询
subqueries = root.findall(".//RelOp[@Action='Subquery']")
if subqueries:
print("警告: 子查询可能不如连接效率。")
# 规则 9: 检查索引扫描
index_scans = root.findall(".//*[@PhysicalOp='Index Scan']")
if index_scans:
print("警告: 查询中存在索引扫描,可能影响性能。")
# 规则 10: 检查内存或磁盘溢出
spills = root.findall(".//SpillToTempDb")
if spills:
print("警告: 查询中存在内存或磁盘溢出,可能影响性能。")
# 规则 11: 检查嵌套循环
nested_loops = root.findall(".//NestedLoops")
if nested_loops:
print("警告: 查询中存在嵌套循环,可能在大数据集上效率低下。")
# 规则 12: 检查是否使用了RIDGE JOIN
ridge_joins = root.findall(".//RidgeJoin")
if ridge_joins:
print("警告: 查询中使用了RIDGE JOIN,可能影响性能。")
# 规则 13: 检查非聚集索引扫描
non_clustered_indexes = [index_scan for index_scan in root.findall(".//IndexScan") if
index_scan.get("Clustered") == "false"]
if non_clustered_indexes:
print("警告: 存在非聚集索引扫描,这可能会导致性能下降。考虑使用聚集索引或重新评估查询设计。")
# 规则 14: 检查转换或隐式转换
conversions = root.findall(".//Convert")
if conversions:
print("警告: 查询中存在数据类型转换或隐式转换,可能会阻止索引的使用。")
# 规则 15: 检查大量的数据移动
data_movements = root.findall(".//*[@PhysicalOp='Parallelism']")
if data_movements:
print("警告: 查询中存在大量的数据移动,如数据溢出到磁盘。")
# 规则 16: 检查任何警告
warnings = root.findall(".//Warnings")
if warnings:
print("警告: 查询中存在警告,例如关于过时的统计信息。")
# 规则 17: 检查连接的顺序
wrong_order_joins = root.findall(".//RelOp[@LogicalOp='Inner Join'][@PhysicalOp!='Nested Loops']")
if wrong_order_joins:
print("警告: 连接的顺序可能不正确,可能影响性能。")
# 规则 18: 检查并行操作限制
parallelism_restrictions = root.findall(".//QueryPlan[@NonParallelPlanReason='MaxDOPSetToOne']")
if parallelism_restrictions:
print("警告: 查询被限制为单线程执行,可能影响性能。")
# 规则 19: 检查过多的物理读取
excessive_physical_reads = root.findall(".//RelOp[PhysicalReads>1000]")
if excessive_physical_reads:
print("警告: 过多的物理读取可能意味着缺少索引或统计信息过时。")
# 规则 20: 检查大量的逻辑读取
excessive_logical_reads = root.findall(".//RelOp[LogicalReads>1000]")
if excessive_logical_reads:
print("警告: 过多的逻辑读取可能影响性能。")
# 规则 21: 检查使用表变量
table_vars = root.findall(".//TableValuedFunction")
if table_vars:
print("警告: 使用表变量可能导致不准确的统计信息。")
# 规则 22: 检查使用OPTION (FORCE ORDER)
force_orders = root.findall(".//Hint[@Type='FORCE ORDER']")
if force_orders:
print("警告: 使用OPTION (FORCE ORDER)可能导致非最佳的查询计划。")
# 规则 23: 检查使用OPTION (OPTIMIZE FOR UNKNOWN)
optimize_for_unknowns = root.findall(".//Hint[@Type='OPTIMIZE FOR UNKNOWN']")
if optimize_for_unknowns:
print("警告: 使用OPTION (OPTIMIZE FOR UNKNOWN)可能导致非最佳的查询计划。")
# 规则 24: 检查缺少统计信息
missing_stats = root.findall(".//MissingStatistics")
if missing_stats:
print("警告: 执行计划中缺少统计信息。")
# 规则 25: 检查过早的物化
early_materializations = root.findall(".//EarlyMaterialization")
if early_materializations:
print("警告: 过早的物化可能导致不必要的I/O。")
# 规则 26: 检查多余的索引扫描
redundant_index_scans = root.findall(".//IndexScan[@Lookup='true']")
if redundant_index_scans:
print("警告: 多余的索引扫描可能影响性能。")
# 规则 27: 检查没有被使用的索引
unused_indexes = root.findall(".//UnusedIndex")
if unused_indexes:
print("警告: 查询中存在没有被使用的索引。")
# 规则 28: 检查没有被推送的谓词
unpushed_predicates = root.findall(".//UnpushedPredicate")
if unpushed_predicates:
print("警告: 谓词没有被推送到存储引擎,可能导致额外的I/O。")
# 规则 29: 检查不支持的物理操作符
unsupported_physical_ops = root.findall(".//UnsupportedPhysicalOp")
if unsupported_physical_ops:
print("警告: 执行计划中使用了不支持的物理操作符。")
# 规则 30: 检查执行计划中的超时
timeouts = root.findall(".//Timeout")
if timeouts:
print("警告: 执行计划中存在超时。")
# 规则 31: 检查重复的谓词
redundant_predicates = root.findall(".//RedundantPredicate")
if redundant_predicates:
print("警告: 查询中存在重复的谓词,可能影响性能。")
# 规则 32: 检查不必要的远程查询
unnecessary_remote_queries = root.findall(".//RemoteQuery[@Unnecessary='true']")
if unnecessary_remote_queries:
print("警告: 执行计划中存在不必要的远程查询。")
# 规则 33: 检查不必要的列
unnecessary_columns = root.findall(".//OutputList/ColumnReference[@Unnecessary='true']")
if unnecessary_columns:
print("警告: 查询返回了不必要的列,可能影响性能。")
# 规则 34: 检查低效的数据类型转换
inefficient_conversions = root.findall(".//Convert[@Implicit='false']")
if inefficient_conversions:
print("警告: 查询中存在低效的数据类型转换。")
# 规则 35: 检查分区切换
partition_switches = root.findall(".//PartitionSwitch")
if partition_switches:
print("警告: 执行计划中存在分区切换,可能导致额外的I/O。")
# 规则 36: 检查低效的TOP操作符
inefficient_tops = root.findall(".//Top[@Percent='false'][@WithTies='true']")
if inefficient_tops:
print("警告: 查询中使用了低效的TOP操作符。")
# 规则 37: 检查未使用的表
unused_tables = [relop for relop in root.findall(".//RelOp") if relop.get("EstimateRows") == "0"]
if unused_tables:
print("警告: 查询中存在未使用的表。这可能是查询设计不当的结果。")
# 规则 38: 检查不必要的DISTINCT
unnecessary_distincts = root.findall(".//Distinct")
if unnecessary_distincts:
print("警告: 查询中使用了不必要的DISTINCT,可能影响性能。")
# 规则 39: 检查不必要的ORDER BY
unnecessary_order_bys = root.findall(".//OrderBy")
if unnecessary_order_bys:
print("警告: 查询中使用了不必要的ORDER BY,可能影响性能。")
# 规则 40: 检查低效的数据排序
inefficient_data_orders = root.findall(".//Sort[@PhysicalOp='Parallelism']")
if inefficient_data_orders:
print("警告: 查询中存在低效的数据排序,可能影响性能。")
# 规则 41: 检查不必要的数据合并
unnecessary_data_merges = root.findall(".//MergeJoin[@ManyToMany='true']")
if unnecessary_data_merges:
print("警告: 查询中存在不必要的数据合并,可能影响性能。")
# 规则 42: 检查不必要的数据串联
unnecessary_data_concats = root.findall(".//Concatenation[@Unordered='true']")
if unnecessary_data_concats:
print("警告: 查询中存在不必要的数据串联,可能影响性能。")
# 规则 43: 检查不必要的数据分割
unnecessary_data_splits = root.findall(".//Split")
if unnecessary_data_splits:
print("警告: 查询中存在不必要的数据分割,可能影响性能。")
# 规则 44: 检查低效的数据压缩
inefficient_data_compressions = root.findall(".//ComputeScalar[@Define='Compression']")
if inefficient_data_compressions:
print("警告: 查询中存在低效的数据压缩,可能影响性能。")
# 规则 45: 检查低效的数据解压缩
inefficient_data_decompressions = root.findall(".//ComputeScalar[@Define='Decompression']")
if inefficient_data_decompressions:
print("警告: 查询中存在低效的数据解压缩,可能影响性能。")
# 规则 46: 检查数据溢出
data_overflows = root.findall(".//RelOp[@EstimateRebinds>0]")
if data_overflows:
print("警告: 执行计划中存在数据溢出,可能导致额外的I/O。")
# 规则 47: 检查使用窗口函数
window_functions = root.findall(".//WindowFunction")
if window_functions:
print("警告: 查询中使用了窗口函数,可能影响性能。")
# 规则 48: 检查昂贵的子查询操作
subquery_ops = root.findall(".//Subquery")
if subquery_ops:
print("警告: 查询中存在昂贵的子查询操作,可能影响性能。")
# 规则 49: 检查过多的嵌套查询
nested_queries = root.findall(".//NestedLoop")
if nested_queries:
print("警告: 查询中存在过多的嵌套查询,可能影响性能。")
# 规则 50: 检查昂贵的递归CTE操作
recursive_cte_ops = root.findall(".//RecursiveCTE")
if recursive_cte_ops:
print("警告: 查询中存在昂贵的递归CTE操作,可能影响性能。")
# 规则 51: 检查昂贵的全文搜索操作
fulltext_search_ops = root.findall(".//FullTextSearch")
if fulltext_search_ops:
print("警告: 查询中存在昂贵的全文搜索操作,可能影响性能。")
# 规则 52: 检查表变量没有统计信息
table_variable_stats = root.findall(".//TableVariableWithoutStats")
if table_variable_stats:
print("警告: 表变量没有统计信息,可能影响查询优化器的决策。")
# 规则 53: 检查分区视图
partitioned_views = root.findall(".//PartitionedView")
if partitioned_views:
print("警告: 分区视图可能导致性能问题。")
# 规则 54: 检查不必要的自连接
self_joins = root.findall(".//Join[@SelfJoin='true']")
if self_joins:
print("警告: 查询中存在不必要的自连接,可能影响性能。")
# 规则 55: 检查索引与数据的物理分离
index_data_disparities = root.findall(".//IndexScan[@PhysicalOp='Remote']")
if index_data_disparities:
print("警告: 索引与其数据在物理上是分开的,可能导致额外的I/O。")
# 规则 56: 检查低效的外连接
inefficient_outer_joins = root.findall(".//OuterJoin[@PhysicalOp='Hash']")
if inefficient_outer_joins:
print("警告: 使用哈希操作的外连接可能不如其他类型的连接效率。")
# 规则 57: 检查未解决的查询提示
unresolved_query_hints = root.findall(".//UnresolvedHint")
if unresolved_query_hints:
print("警告: 查询中存在未解决的查询提示。")
# 规则 58: 检查使用了过时的查询提示
deprecated_query_hints = root.findall(".//DeprecatedHint")
if deprecated_query_hints:
print("警告: 查询中使用了过时的查询提示。")
# 规则 59: 检查昂贵的动态SQL操作
dynamic_sql_ops = root.findall(".//DynamicSQL")
if dynamic_sql_ops:
print("警告: 查询中存在昂贵的动态SQL操作,可能影响性能。")
# 规则 60: 检查昂贵的递归查询
recursive_queries = root.findall(".//RecursiveQuery")
if recursive_queries:
print("警告: 查询中存在昂贵的递归查询,可能影响性能。")
# 规则 61: 检查未使用的表别名
unused_table_aliases = root.findall(".//UnusedAlias")
if unused_table_aliases:
print("警告: 查询中存在未使用的表别名,可能导致查询难以理解。")
# 规则 62: 检查昂贵的列存储扫描
columnstore_scans = root.findall(".//ColumnstoreScan")
if columnstore_scans:
print("警告: 查询中存在昂贵的列存储扫描,可能影响性能。")
# 规则 63: 检查昂贵的列存储索引操作
columnstore_index_ops = root.findall(".//ColumnstoreIndex")
if columnstore_index_ops:
print("警告: 查询中存在昂贵的列存储索引操作,可能影响性能。")
# 规则 64: 检查使用了大量的内存的操作
high_memory_ops = root.findall(".//RelOp[@Memory>5000]") # Arbitrary threshold
if high_memory_ops:
print("警告: 查询中存在使用了大量内存的操作,可能影响性能。")
# 规则 65: 检查使用了大量的CPU的操作
high_cpu_ops = root.findall(".//RelOp[@CPU>1000]") # Arbitrary threshold
if high_cpu_ops:
print("警告: 查询中存在使用了大量CPU的操作,可能影响性能。")
# 规则 66: 检查低效的数据聚合
inefficient_aggregations = root.findall(".//Aggregate[@Strategy='Hash']")
if inefficient_aggregations:
print("警告: 查询中存在低效的数据聚合,可能影响性能。")
# 规则 67: 检查在大数据集上的嵌套循环
large_data_set_loops = root.findall(".//NestedLoop[@LargeDataSet='true']")
if large_data_set_loops:
print("警告: 查询在大数据集上使用嵌套循环,可能影响性能。")
# 规则 68: 检查不必要的数据复制
data_copies = root.findall(".//Copy")
if data_copies:
print("警告: 查询中存在不必要的数据复制,可能影响性能。")
# 规则 69: 检查昂贵的数据插入
expensive_inserts = root.findall(".//Insert")
if expensive_inserts:
print("警告: 查询中存在昂贵的数据插入操作,可能影响性能。")
# 规则 70: 检查昂贵的数据更新
expensive_updates = root.findall(".//Update")
if expensive_updates:
print("警告: 查询中存在昂贵的数据更新操作,可能影响性能。")
# 规则 71: 检查昂贵的数据删除
expensive_deletes = root.findall(".//Delete")
if expensive_deletes:
print("警告: 查询中存在昂贵的数据删除操作,可能影响性能。")
# 规则 72: 检查昂贵的数据合并
expensive_merges = root.findall(".//Merge")
if expensive_merges:
print("警告: 查询中存在昂贵的数据合并操作,可能影响性能。")
# 规则 73: 检查不必要的数据转换
unnecessary_conversions = root.findall(".//Convert")
if unnecessary_conversions:
print("警告: 查询中存在不必要的数据转换,可能影响性能。")
# 规则 74: 检查数据转换的错误
conversion_errors = root.findall(".//Convert[@Error='true']")
if conversion_errors:
print("警告: 查询中的数据转换存在错误。")
# 规则 75: 检查不必要的数据连接
unnecessary_data_links = root.findall(".//DataLink")
if unnecessary_data_links:
print("警告: 查询中存在不必要的数据连接,可能影响性能。")
# 规则 76: 检查不必要的数据流
unnecessary_data_streams = root.findall(".//Stream")
if unnecessary_data_streams:
print("警告: 查询中存在不必要的数据流,可能影响性能。")
# 规则 77: 检查数据流的错误
stream_errors = root.findall(".//Stream[@Error='true']")
if stream_errors:
print("警告: 查询中的数据流存在错误。")
# 规则 78: 检查昂贵的数据分区操作
expensive_partitions = root.findall(".//Partition")
if expensive_partitions:
print("警告: 查询中存在昂贵的数据分区操作,可能影响性能。")
# 规则 79: 检查昂贵的数据压缩操作
expensive_compressions = root.findall(".//Compression")
if expensive_compressions:
print("警告: 查询中存在昂贵的数据压缩操作,可能影响性能。")
# 规则 80: 检查昂贵的数据解压缩操作
expensive_decompressions = root.findall(".//Decompression")
if expensive_decompressions:
print("警告: 查询中存在昂贵的数据解压缩操作,可能影响性能。")
# 规则 81: 检查昂贵的数据分发操作
expensive_distributions = root.findall(".//Distribution")
if expensive_distributions:
print("警告: 查询中存在昂贵的数据分发操作,可能影响性能。")
# 规则 82: 检查不平衡的数据分发
unbalanced_distributions = root.findall(".//Distribution[@Balance='false']")
if unbalanced_distributions:
print("警告: 数据分发不平衡,可能导致资源浪费。")
# # 规则 83: 检查查询的I/O成本
# # 注意: 这需要具体的阈值和数据库的实际I/O成本数据,此处只是一个示例
# io_cost = float(root.find(".//QueryPlan").get('TotalSubtreeCost', '0'))
# if io_cost > 50: # 假设阈值为50,实际值需要根据具体情况确定
# print("警告: 查询的I/O成本异常高,考虑优化查询或相关配置。")
# 规则 83: 检查查询的I/O成本
# 注意: 这需要具体的阈值和数据库的实际I/O成本数据,此处只是一个示例
query_plan_element = root.find(".//QueryPlan")
if query_plan_element is not None:
io_cost = float(query_plan_element.get('TotalSubtreeCost', '0'))
if io_cost > 50: # 假设阈值为50,实际值需要根据具体情况确定
print("警告: 查询的I/O成本异常高,考虑优化查询或相关配置。")
# 规则 84: 检查不必要的数据分隔
unnecessary_data_separations = root.findall(".//Separation")
if unnecessary_data_separations:
print("警告: 查询中存在不必要的数据分隔,可能影响性能。")
# 规则 85: 检查昂贵的数据分隔操作
expensive_separations = root.findall(".//Separation")
if expensive_separations:
print("警告: 查询中存在昂贵的数据分隔操作,可能影响性能。")
# 规则 86: 检查数据阻塞
data_blockages = root.findall(".//Blockage")
if data_blockages:
print("警告: 数据阻塞可能导致性能问题。")
# 规则 87: 检查数据锁
data_locks = root.findall(".//Lock")
if data_locks:
print("警告: 数据锁可能导致性能问题。")
# 规则 88: 检查数据死锁
data_deadlocks = root.findall(".//Deadlock")
if data_deadlocks:
print("警告: 数据死锁可能导致查询失败。")
# 规则 89: 检查低效的数据缓存
inefficient_data_caching = root.findall(".//Cache[@Efficiency='low']")
if inefficient_data_caching:
print("警告: 低效的数据缓存可能导致性能问题。")
# 规则 90: 检查不必要的数据重复
unnecessary_data_replications = root.findall(".//Replication")
if unnecessary_data_replications:
print("警告: 查询中存在不必要的数据重复,可能影响性能。")
# 规则 91: 检查昂贵的数据重复操作
expensive_replications = root.findall(".//Replication")
if expensive_replications:
print("警告: 查询中存在昂贵的数据重复操作,可能影响性能。")
# 规则 92: 检查数据负载不平衡
data_load_imbalances = root.findall(".//Load[@Balance='false']")
if data_load_imbalances:
print("警告: 数据负载不平衡,可能导致资源浪费。")
# 规则 93: 检查数据溢出
data_spills = root.findall(".//Spill")
if data_spills:
print("警告: 数据溢出可能导致性能问题。")
# 规则 94: 检查数据泄漏
data_leaks = root.findall(".//Leak")
if data_leaks:
print("警告: 数据泄漏可能导致安全问题。")
# 规则 95: 检查数据冲突
data_conflicts = root.findall(".//Conflict")
if data_conflicts:
print("警告: 数据冲突可能导致查询失败。")
# 规则 96: 检查使用非sargable操作
non_sargable_ops = root.findall(".//NonSargable")
if non_sargable_ops:
print("警告: 查询中存在非sargable操作,可能影响性能。")
# 规则 97: 检查数据分布不均
data_distribution_imbalances = root.findall(".//Distribution[@Even='false']")
if data_distribution_imbalances:
print("警告: 数据分布不均,可能导致资源浪费。")
# 规则 98: 检查数据碎片
data_fragments = root.findall(".//Fragmentation")
if data_fragments:
print("警告: 数据碎片可能导致性能问题。")
# 规则 99: 检查数据冗余
data_redundancies = root.findall(".//Redundancy")
if data_redundancies:
print("警告: 数据冗余可能导致资源浪费。")
# 规则 100: 检查大量的UNION操作
excessive_unions = root.findall(".//Union")
if excessive_unions:
print("警告: 查询中存在大量的UNION操作,可能影响性能。")
# 规则 101: 检查表扫描操作
table_scans = root.findall(".//TableScan")
if table_scans:
print("警告: 查询中存在表扫描操作,可能影响性能。考虑添加适当的索引。")
# 规则 102: 检查索引扫描
index_scans = root.findall(".//IndexScan")
if index_scans:
print("警告: 查询中存在索引扫描,而不是索引查找。考虑修改查询或优化索引。")
# 规则 103: 检查高代价操作 √
high_cost_ops = [op for op in root.findall(".//*") if float(op.get('EstimatedTotalSubtreeCost', 0)) > 10.0]
if high_cost_ops:
print("警告: 查询中存在高代价的操作,可能影响性能。")
# 规则 104: 检查RID查找
rid_lookups = root.findall(".//RIDLookup")
if rid_lookups:
print("警告: 查询中存在RID查找,这可能是因为缺少覆盖索引。考虑优化索引。")
# 规则 105: 检查大型哈希聚合
large_hash_aggregates = root.findall(".//HashMatch[@AggregateType='Hash']")
if large_hash_aggregates:
print("警告: 查询中存在大型哈希聚合操作,可能导致大量的内存使用。")
# 规则 106: 检查并行操作中的数据流不均衡
parallel_imbalance = root.findall(".//Parallelism[@Reason='DataFlow']")
if parallel_imbalance:
print("警告: 查询中的并行操作存在数据流不均衡,可能导致性能下降。")
# 规则 107: 检查计算密集型操作
compute_intensive = [op for op in root.findall(".//*") if float(op.get('ComputeScalar', 0)) > 0.2]
if compute_intensive:
print("警告: 查询中存在计算密集型操作,可能影响性能。")
# 规则 108: 检查数据移动操作
data_movement = root.findall(".//Spool")
if data_movement:
print("警告: 查询中存在数据移动操作,可能影响性能。")
# 规则 109: 检查外部表操作
external_table_ops = root.findall(".//RemoteQuery")
if external_table_ops:
print("警告: 查询中存在外部表操作,可能影响性能。")
# 规则 110: 重复删除
# 规则 111: 检查哈希连接
hash_joins = root.findall(".//HashMatch[@JoinType='Inner']")
if hash_joins:
print("警告: 查询中存在哈希连接,可能需要大量内存。考虑优化连接策略。")
# 规则 112: 检查"Missing Index"提示
missing_index_warnings = root.findall(".//MissingIndex")
if missing_index_warnings:
print("警告: 执行计划中有'Missing Index'提示,考虑添加建议的索引来提高性能。")
# 规则 113: 检查键查找
key_lookups = root.findall(".//KeyLookup")
if key_lookups:
print("警告: 查询中存在键查找操作,可能导致性能问题。考虑使用覆盖索引。")
# 规则 114: 检查递归操作
recursive_ops = root.findall(".//Recursive")
if recursive_ops:
print("警告: 查询中存在递归操作,可能影响性能。")
# 规则 115: 检查并行操作是否因为资源争夺被阻塞
parallel_blocked = [op for op in root.findall(".//Parallelism") if op.get('Blocked', 0) == '1']
if parallel_blocked:
print("警告: 查询中的并行操作被阻塞,可能是因为资源争夺。")
# 规则 116: 检查转换操作
convert_ops = root.findall(".//Convert")
if convert_ops:
print("警告: 查询中存在数据类型转换操作,可能影响性能。确保查询中使用的数据类型匹配表结构的数据类型。")
# 规则 117: 检查流水线操作
stream_aggregate = root.findall(".//StreamAggregate")
if stream_aggregate:
print("警告: 查询中存在流水线聚合操作,可能需要优化。")
# 规则 118: 检查内存溢出到磁盘的操作
spill_to_tempdb = [op for op in root.findall(".//*") if float(op.get('EstimatedSpillLevel', 0)) > 0]
if spill_to_tempdb:
print("警告: 查询中的某些操作可能导致内存溢出到tempdb,可能影响性能。")
# 规则 119: 检查未使用的统计信息
unused_stats = root.findall(".//StatisticsNotUsed")
if unused_stats:
print("警告: 查询中存在未使用的统计信息,考虑更新或删除不必要的统计信息。")
# 规则 120: 检查非最优的位图操作
bitmap_ops = root.findall(".//Bitmap")
if bitmap_ops:
print("警告: 查询中存在位图操作,可能影响性能。考虑优化相关的连接或筛选条件。")
# 规则 121: 检查高成本的远程查询
remote_query = root.findall(".//RemoteQuery")
if remote_query:
print("警告: 查询中存在高成本的远程查询操作,可能影响性能。考虑优化远程查询或将数据本地化。")
# 规则 122: 检查表变量操作
table_var_ops = root.findall(".//TableValuedFunction")
if table_var_ops:
print("警告: 查询中存在表变量操作,可能导致性能下降。考虑使用临时表替代表变量。")
# 规则 123: 检查大量的RID查找(堆查找)
rid_lookups = root.findall(".//RIDLookup")
if rid_lookups:
print("警告: 查询中存在大量的RID查找操作,这是堆查找,可能导致性能问题。考虑使用聚集索引。")
# 规则 124: 检查Left Outer Join操作,可能意味着查询中有左外连接
left_outer_join_operations = root.findall(".//*[@PhysicalOp='Left Outer Join']")
if left_outer_join_operations:
print("警告: 查询中存在Left Outer Join操作,考虑是否可以优化连接策略。")
# 规则 125: 检查序列投影操作
sequence_project = root.findall(".//SequenceProject")
if sequence_project:
print("警告: 查询中存在序列投影操作,可能影响性能。")
# 规则 126: 检查窗口函数操作
window_aggregates = root.findall(".//WindowAggregate")
if window_aggregates:
print("警告: 查询中存在窗口函数操作,可能影响性能。考虑优化窗口函数或相关查询。")
# 规则 127: 检查顶部操作
top_ops = root.findall(".//Top")
if top_ops:
print("警告: 查询中存在TOP操作,可能导致性能下降。确保只检索所需的记录数。")
# 规则 128: 检查嵌套循环连接中的异步操作
async_nested_loops = root.findall(".//NestedLoops[@IsAsync='True']")
if async_nested_loops:
print("警告: 查询中的嵌套循环连接存在异步操作,可能导致性能问题。考虑优化连接策略。")
# 规则 129: 检查分配给查询的过多内存
high_memory_grants = [op for op in root.findall(".//MemoryGrant") if
float(op.get('SerialRequiredMemory', 0)) > 1048576]
if high_memory_grants:
print("警告: 查询被分配了过多的内存,可能导致其他查询资源争夺。考虑优化查询以减少内存使用。")
# 规则 130: 检查表的扫描操作而不是索引的扫描
full_table_scans = root.findall(".//TableScan")
if full_table_scans:
print("警告: 查询中存在全表扫描操作,可能影响性能。考虑使用或优化索引以减少全表扫描。")
# 规则 131: 检查哈希递归操作
hash_recursive = root.findall(".//Hash[@Recursive='True']")
if hash_recursive:
print("警告: 查询中存在哈希递归操作,可能影响性能。考虑优化相关的连接策略。")
# 规则 132: 检查高度并行的操作
highly_parallel_ops = [op for op in root.findall(".//RelOp") if int(op.get('Parallel', 0)) > 8]
if highly_parallel_ops:
print("警告: 查询中存在高度并行的操作,可能导致资源争夺。考虑调整查询或并行度设置。")
# 规则 133: 检查流水线函数调用
streaming_udfs = root.findall(".//StreamingUDF")
if streaming_udfs:
print("警告: 查询中存在流水线UDF调用,可能导致性能下降。考虑优化或避免使用流水线UDF。")
# 规则 134: 检查高开销的UDF调用
high_cost_udfs = [op for op in root.findall(".//UDF") if float(op.get('EstimateTotalSubtreeCost', 0)) > 10]
if high_cost_udfs:
print("警告: 查询中存在高开销的UDF调用,可能影响性能。考虑优化或避免使用这些UDF。")
# 规则 135: 检查大量的外部表操作
external_table_ops = root.findall(".//ExternalTable")
if external_table_ops:
print("警告: 查询中存在大量的外部表操作,可能导致性能问题。考虑将数据本地化或优化外部查询。")
# 规则 136: 检查不优化的子查询
unoptimized_subqueries = root.findall(".//UnoptimizedSubquery")
if unoptimized_subqueries:
print("警告: 查询中存在不优化的子查询,可能导致性能问题。考虑重写子查询或将其转化为连接操作。")
# 规则 137: 检查高开销的动态SQL操作
dynamic_sql_ops = [op for op in root.findall(".//DynamicSQL") if float(op.get('EstimateTotalSubtreeCost', 0)) > 10]
if dynamic_sql_ops:
print("警告: 查询中存在高开销的动态SQL操作,可能影响性能。考虑优化或避免使用动态SQL。")
# 规则 138: 检查数据移动操作
data_movement_ops = root.findall(".//DataMovement")
if data_movement_ops:
print("警告: 查询中存在数据移动操作,可能导致性能下降。考虑优化查询或数据分布策略。")
# 规则 139: 检查列存储索引扫描的不优化操作
non_optimized_columnstore = root.findall(".//ColumnStoreIndexScan[@Optimized='False']")
if non_optimized_columnstore:
print("警告: 查询中的列存储索引扫描未被优化,可能影响性能。考虑优化查询或列存储索引设置。")
# 规则 140: 检查排序操作中的高内存使用
high_mem_sorts = [op for op in root.findall(".//Sort") if float(op.get('MemoryFractions', 0)) > 0.5]
if high_mem_sorts:
print("警告: 查询中的排序操作使用了大量内存,可能导致资源争夺。考虑优化查询或调整资源分配。")
# 规则 141: 检查 Bitmap 过滤器操作
bitmap_filters = root.findall(".//Bitmap")
if bitmap_filters:
print(
"警告: 查询中存在 Bitmap 过滤器操作。虽然这些操作有时可以提高性能,但在某些情况下它们可能导致性能下降。考虑对相关查询进行优化。")
# 规则 142: 检查计算标量操作
compute_scalars = root.findall(".//ComputeScalar")
if compute_scalars:
print("警告: 查询中存在大量的计算标量操作,可能导致CPU开销增加。考虑优化相关的标量计算或将其移到应用程序中进行。")
# 规则 143: 检查嵌套循环连接
nested_loops = root.findall(".//NestedLoops")
if nested_loops:
print("警告: 查询中存在嵌套循环连接,这可能在大数据集上效率较低。考虑优化连接策略或确保相关列已经进行了索引。")
# 规则 144: 检查远程查询
remote_queries = root.findall(".//RemoteQuery")
if remote_queries:
print("警告: 查询中存在远程查询操作,可能导致网络开销增加。考虑将数据本地化或优化远程查询。")
# 规则 145: 检查表变量操作
table_vars = root.findall(".//TableVariable")
if table_vars:
print("警告: 查询中使用了表变量,这可能在某些情况下效率较低。考虑使用临时表或优化表变量使用。")
# 规则 146: 检查 TVF (表值函数) 扫描
tvf_scans = root.findall(".//TableValuedFunction")
if tvf_scans:
print("警告: 查询中存在表值函数(TVF)扫描,可能导致性能下降。考虑优化 TVF 或使用其他方法重写查询。")
# 规则 147: 检查 Sort 操作中的警告
sort_warnings = [op for op in root.findall(".//Sort") if op.get('WithAbortOption', 'False') == 'True']
if sort_warnings:
print("警告: 查询中的排序操作存在潜在的中止选项,可能导致查询提前结束。确保为排序操作提供足够的资源或优化查询。")
# 规则 148: 检查 Spool 操作
spool_ops = root.findall(".//Spool")
if spool_ops:
print("警告: 查询中存在 Spool 操作,可能导致磁盘开销增加。考虑优化查询以减少或消除 Spool 操作。")
# 规则 149: 检查 Window 函数操作
window_funcs = root.findall(".//Window")
if window_funcs:
print("警告: 查询中使用了窗口函数,可能导致性能下降。考虑优化窗口函数的使用或重写查询。")
# 规则 150: 检查交叉应用操作
cross_app_ops = root.findall(".//CrossApp")
if cross_app_ops:
print("警告: 查询中存在跨应用操作,可能导致性能和数据一致性问题。考虑将数据移动到同一应用或优化跨应用查询。")
# 规则 151: 检查哈希匹配操作
hash_matches = root.findall(".//HashMatch")
if hash_matches:
print("警告: 查询中存在哈希匹配操作,可能导致内存开销增加。考虑优化连接策略或确保相关列已经进行了索引。")
# 规则 152: 检查高代价的流操作
high_cost_streams = [op for op in root.findall(".//RelOp") if float(op.get('EstimatedTotalSubtreeCost', 0)) > 10]
if high_cost_streams:
print("警告: 查询中存在高代价的流操作,可能导致性能下降。仔细检查这些操作并考虑进行优化。")
# 规则 153: 检查非平行查询操作
non_parallel_ops = root.findall(".//NonParallelPlanReason")
if non_parallel_ops:
print("警告: 查询未能并行执行。考虑优化查询或检查服务器设置以支持并行处理。")
# 规则 154: 检查大型数据移动操作
data_movement_ops = root.findall(".//DataMovement")
if data_movement_ops:
print("警告: 查询中存在大型数据移动操作,可能导致网络或磁盘开销增加。考虑优化查询或数据库结构。")
# 规则 155: 检查大型删除操作
delete_ops = [op for op in root.findall(".//Delete") if int(op.get('RowCount', 0)) > 10000]
if delete_ops:
print("警告: 查询中执行了大量的删除操作,可能导致性能下降或锁定问题。考虑分批进行删除或优化删除策略。")
# 规则 156: 检查多表连接操作
multi_table_joins = root.findall(".//Join[@PhysicalOp='MultiTableJoin']")
if multi_table_joins:
print("警告: 查询中存在多表连接操作,可能导致性能下降。考虑重写查询或优化连接策略。")
# 规则 157: 检查列存储索引的效率
columnstore_scans = root.findall(".//ColumnStoreIndexScan")
if columnstore_scans:
print("警告: 查询中存在列存储索引扫描,但可能没有充分利用列存储的优势。考虑优化查询或检查列存储索引的设计。")
# 规则 158: 检查排序操作的内存开销
sort_memory_issues = [op for op in root.findall(".//Sort") if float(op.get('MemoryFraction', 0)) > 0.5]
if sort_memory_issues:
print("警告: 查询中的排序操作使用了大量的内存。考虑优化排序操作或增加查询的内存配额。")
# 规则 159: 检查潜在的死锁操作
potential_deadlocks = root.findall(".//Deadlock")
if potential_deadlocks:
print("警告: 查询中存在可能导致死锁的操作。考虑重写查询或调整事务隔离级别。")
# 规则 160: 检查全文搜索操作的效率
fulltext_searches = root.findall(".//FullTextSearch")
if fulltext_searches:
print("警告: 查询中使用了全文搜索,但可能没有充分优化。考虑检查全文索引或优化全文查询。")
# 规则 161: 检查嵌套循环连接操作
nested_loops = root.findall(".//NestedLoops")
if nested_loops:
print("警告: 查询中存在嵌套循环连接操作,可能会影响大数据集的性能。")
# 规则 162: 检查哈希匹配连接操作
hash_matches = root.findall(".//HashMatch")
if hash_matches:
print("警告: 查询中存在哈希匹配连接操作,可能会导致额外的I/O和CPU负担。")
# 规则 163: 检查表变量的使用
table_vars = root.findall(".//TableValuedFunction")
if table_vars:
print("警告: 查询中使用了表变量,可能会影响性能,尤其是在大数据集上。")
# 规则 164: 检查RID Lookup操作
rid_lookup = root.findall(".//RIDLookup")
if rid_lookup:
print("警告: 查询中存在RID Lookup操作,这通常意味着缺少聚集索引。")
# 规则 165: 检查Filter操作
filters = root.findall(".//Filter")
if filters:
print("警告: 查询中存在Filter操作,可能会导致查询性能下降。")
# 规则 166: 检查并行操作
parallel_ops = root.findall(".//Parallelism")
if parallel_ops:
print("警告: 查询中存在并行操作,可能会导致资源争用和性能下降。")
# 规则 167: 检查Sort操作
sort_ops = root.findall(".//Sort")
if sort_ops:
print("警告: 查询中存在Sort操作,大量的排序可能会消耗大量的CPU和内存。")
# 规则 168: 检查Compute Scalar操作 √
compute_scalar_ops = root.findall(".//*[@PhysicalOp='Compute Scalar']")
if compute_scalar_ops:
print("警告: 查询中存在Compute Scalar操作,可能会导致额外的计算开销,并且可能有计算可以优化。")
# 规则 169: 重复删除
# 规则 170: 重复删除
# 规则 171: 检查Convert操作
convert_ops = root.findall(".//Convert")
if convert_ops:
print("警告: 查询中存在数据类型转换操作,可能会导致性能下降。")
# 规则 172: 检查Constant Scan操作
constant_scan_ops = root.findall(".//ConstantScan")
if constant_scan_ops:
print("警告: 查询中存在Constant Scan操作,可能影响查询性能。")
# 规则 173: 检查外部表连接
external_table_joins = root.findall(".//RemoteQuery")
if external_table_joins:
print("警告: 查询涉及外部表连接,可能导致性能问题。")
# 规则 174: 检查Sparse Column操作
sparse_column_ops = root.findall(".//SparseColumnOperator")
if sparse_column_ops:
print("警告: 查询中使用了稀疏列,这可能会影响性能。")
# 规则 175: 检查TOP操作
top_ops = root.findall(".//Top")
if top_ops:
print("警告: 查询中使用了TOP操作,可能导致性能问题,尤其是当未与ORDER BY结合使用时。")
# 规则 176: 检查UDF (用户定义函数) 的使用
udf_ops = root.findall(".//UserDefinedFunction")
if udf_ops:
print("警告: 查询中使用了用户定义的函数,这可能导致性能问题。")
# 规则 177: 检查Window Aggregate操作
window_aggregate_ops = root.findall(".//WindowAggregate")
if window_aggregate_ops:
print("警告: 查询中使用了窗口聚合函数,可能导致性能问题。")
# 规则 178: 检查XML运算操作
xml_ops = root.findall(".//XmlReader")
if xml_ops:
print("警告: 查询中存在XML操作,可能会影响性能。")
# 规则 179: 检查全文索引查询
fulltext_query = root.findall(".//Contains")
if fulltext_query:
print("警告: 查询中使用了全文索引查询,可能导致性能问题。")
# 规则 180: 检查动态SQL操作
dynamic_sql_ops = root.findall(".//Dynamic")
if dynamic_sql_ops:
print("警告: 查询中存在动态SQL操作,可能导致性能和安全问题。")
# 规则 181: 重复删除
# 规则 182: 检查悬挂的外部连接
unmatched_outer_joins = root.findall(".//UnmatchedOuterJoin")
if unmatched_outer_joins:
print("警告: 查询中存在悬挂的外部连接,可能导致性能问题。")
# 规则 183: 检查表值函数
table_valued_function = root.findall(".//TableValuedFunction")
if table_valued_function:
print("警告: 查询中使用了表值函数,可能导致性能问题。")
# 规则 184: 检查列存储索引扫描
column_store_scan = root.findall(".//ColumnStoreIndexScan")
if column_store_scan:
print("警告: 查询中使用了列存储索引扫描,可能导致性能问题。")
# 规则 185: 检查列存储索引查找
column_store_seek = root.findall(".//ColumnStoreIndexSeek")
if column_store_seek:
print("警告: 查询中使用了列存储索引查找,可能导致性能问题。")
# 规则 186: 检查列存储哈希匹配
column_store_hash = root.findall(".//ColumnStoreHashJoin")
if column_store_hash:
print("警告: 查询中使用了列存储哈希匹配,可能导致性能问题。")
# 规则 187: 检查非优化的嵌套循环
non_optimized_loops = root.findall(".//NestedLoops")
if non_optimized_loops:
print("警告: 查询中存在非优化的嵌套循环,可能导致性能问题。")
# 规则 188: 检查递归查询
recursive_cte = root.findall(".//RecursiveCTE")
if recursive_cte:
print("警告: 查询中使用了递归公共表达式,可能导致性能问题。")
# 规则 189: 重复删除
# 规则 190: 检查非参数化查询