Skip to content

Commit 4ffb60c

Browse files
authored
Added basic elements for QueryProfilerComparison (#1280)
* Added basic elements for QueryProfilerComparison To do: - The METRIC part of the accordion is not working yet. * black * Update qprof_interface.py * Now the interaction is working completely fine
1 parent 0fe6b73 commit 4ffb60c

File tree

2 files changed

+110
-7
lines changed

2 files changed

+110
-7
lines changed

verticapy/performance/vertica/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@
1515
permissions and limitations under the License.
1616
"""
1717
from verticapy.performance.vertica.qprof import QueryProfiler
18-
from verticapy.performance.vertica.qprof_interface import QueryProfilerInterface
18+
from verticapy.performance.vertica.qprof_interface import (
19+
QueryProfilerInterface,
20+
QueryProfilerComparison,
21+
)
1922
from verticapy.performance.vertica.qprof_stats_tests import QueryProfilerStats

verticapy/performance/vertica/qprof_interface.py

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ def __init__(
7272
value=False, description="Qsteps switch", disabled=False, indent=False
7373
)
7474

75+
self.accordions = None
76+
7577
# buttons to navigate through transactions
7678
next_button = widgets.Button(description="Next Query")
7779
prev_button = widgets.Button(description="Previous Query")
@@ -153,7 +155,7 @@ def __init__(
153155
value=f"<h1><b>Query Execution Steps - [query_idx: {self.index_widget.value}]</b></h1>"
154156
)
155157

156-
def get_qplan_tree(self, use_javascript=True, **style_kwargs):
158+
def get_qplan_tree(self, use_javascript=True, hide_settings=False, **style_kwargs):
157159
"""
158160
Draws an interactive Query plan tree.
159161
@@ -270,10 +272,10 @@ def get_qplan_tree(self, use_javascript=True, **style_kwargs):
270272
"Query text": self.query_display,
271273
}
272274
query_text_index = list(accordion_items.keys()).index("Query text")
273-
accordions = Visualizer._accordion(
275+
self.accordions = Visualizer._accordion(
274276
list(accordion_items.values()), accordion_items.keys()
275277
)
276-
accordions.selected_index = query_text_index
278+
self.accordions.selected_index = query_text_index
277279
header_box = widgets.HBox(
278280
[self.qpt_header], layout={"justify_content": "center"}
279281
)
@@ -292,14 +294,21 @@ def get_qplan_tree(self, use_javascript=True, **style_kwargs):
292294
interactive_output = widgets.interactive_output(
293295
self.update_qplan_tree, controls
294296
)
297+
if hide_settings:
298+
self.accordions.layout.display = "none"
299+
self.transaction_buttons.layout.display = "none"
300+
self.query_select_dropdown.layout.display = "none"
301+
self.query_display_info.layout.display = "none"
295302
settings = [
296-
accordions,
303+
self.accordions,
297304
self.transaction_buttons,
298305
self.query_select_dropdown,
299306
self.query_display_info,
300307
]
301308
viz = Visualizer(
302-
settings_wids=settings, graph_wids=[header_box, interactive_output]
309+
settings_wids=settings,
310+
graph_wids=[header_box, interactive_output],
311+
orientation="v" if hide_settings else "h",
303312
)
304313
viz.display()
305314

@@ -533,7 +542,7 @@ def get_qsteps_(self):
533542
list(accordion_items.values()), accordion_items.keys()
534543
)
535544
qsteps_settings = [
536-
accordions,
545+
self.accordions,
537546
self.transaction_buttons,
538547
]
539548

@@ -734,3 +743,94 @@ def get_step_funcs(self):
734743
20: self.get_rp_status,
735744
21: self.get_cluster_config,
736745
}
746+
747+
748+
class QueryProfilerComparison:
749+
"""
750+
Initializes a QueryProfilerComparison object with two QueryProfilerInterface instances for side-by-side comparison.
751+
752+
Parameters:
753+
qprof1 (QueryProfilerInterface): The first QueryProfilerInterface instance for comparison.
754+
qprof2 (QueryProfilerInterface): The second QueryProfilerInterface instance for comparison.
755+
"""
756+
757+
def __init__(self, qprof1, qprof2):
758+
self.qprof1 = qprof1
759+
self.qprof2 = qprof2
760+
761+
self.query_info = self._create_query_info()
762+
763+
# Initial update of the trees
764+
nooutput = widgets.Output()
765+
with nooutput:
766+
self.qprof1.get_qplan_tree()
767+
self.qprof2.get_qplan_tree()
768+
769+
self.controls = self._create_controls()
770+
self.side_by_side_ui = widgets.VBox([self.query_info, self.controls])
771+
772+
def _create_controls(self):
773+
def create_interactive_controls(qprof):
774+
controls = {
775+
"index": qprof.query_select_dropdown,
776+
"metric1": qprof.accordions.children[0].children[0],
777+
"metric2": qprof.accordions.children[0].children[1],
778+
"display_tooltip_agg_metrics": qprof.accordions.children[0]
779+
.children[3]
780+
.children[0],
781+
"display_tooltip_op_metrics": qprof.accordions.children[0]
782+
.children[3]
783+
.children[1],
784+
"display_tooltip_descriptors": qprof.accordions.children[0]
785+
.children[3]
786+
.children[2],
787+
"path_id": qprof.pathid_dropdown.get_child(),
788+
"apply_tree_clicked": qprof.apply_tree,
789+
"temp_display": qprof.accordions.children[2].children[0],
790+
"projection_display": qprof.accordions.children[2].children[1],
791+
}
792+
return widgets.interactive_output(qprof.update_qplan_tree, controls)
793+
794+
q1_control = self.qprof1.accordions
795+
q1_control.selected_index = None
796+
q1_control.layout.width = "50%"
797+
q1_interactive = create_interactive_controls(self.qprof1)
798+
q1_interactive = widgets.HBox(
799+
[q1_interactive],
800+
layout=widgets.Layout(width="50%", border="1px solid black"),
801+
)
802+
803+
q2_control = self.qprof2.accordions
804+
q2_control.selected_index = None
805+
q2_control.layout.width = "50%"
806+
q2_interactive = create_interactive_controls(self.qprof2)
807+
q2_interactive = widgets.HBox(
808+
[q2_interactive],
809+
layout=widgets.Layout(width="50%", border="1px solid black"),
810+
)
811+
812+
return widgets.VBox(
813+
[
814+
widgets.HBox([q1_control, q2_control]),
815+
widgets.HBox([q1_interactive, q2_interactive]),
816+
]
817+
)
818+
819+
def _create_query_info(self):
820+
# Get and set the layout for the query display info for both qprof1 and qprof2
821+
q1_info = self.qprof1.query_display_info
822+
q1_info.layout.display = "block"
823+
q1_info.layout.width = "50%"
824+
q1_info.layout.border = "1px solid black"
825+
826+
q2_info = self.qprof2.query_display_info
827+
q2_info.layout.display = "block"
828+
q2_info.layout.width = "50%"
829+
q2_info.layout.border = "1px solid black"
830+
831+
# Return an HBox containing the query display information side by side
832+
return widgets.HBox([q1_info, q2_info])
833+
834+
def display(self):
835+
# Display the final side-by-side UI
836+
display(self.side_by_side_ui)

0 commit comments

Comments
 (0)