Skip to content

Commit

Permalink
chore(db-analyzer): database size analyzer and optimizer ui added
Browse files Browse the repository at this point in the history
  • Loading branch information
tanmoysrt committed Dec 20, 2024
1 parent 77072ba commit 5ae9332
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
v-if="selectedSchema"
/>
</div>
<div class="mt-3 flex flex-row gap-2" v-if="selectedSchema">
<div
class="mt-3 flex flex-row gap-2"
v-if="selectedSchema && showSQLActions"
>
<Button
iconLeft="play"
class="grow"
Expand Down Expand Up @@ -56,7 +59,24 @@ import { toast } from 'vue-sonner';
export default {
name: 'DatabaseTableSchemaDialog',
props: ['site', 'tableSchemas'],
props: {
site: {
type: String,
required: true
},
tableSchemas: {
type: Object,
required: true
},
showSQLActions: {
type: Boolean,
default: false
},
preSelectedSchema: {
type: String,
default: null
}
},
emits: ['runSQLQuery'],
components: {
FormControl,
Expand All @@ -67,18 +87,28 @@ export default {
selectedSchema: null
};
},
mounted() {
this.preSelectSchema();
},
watch: {
preSelectedSchema() {
this.preSelectSchema();
}
},
computed: {
autocompleteOptions() {
return Object.keys(this.tableSchemas).map(x => ({
label: x,
label: `${x} (${this.bytesToMB(
this.tableSchemas[x].size.total_size
)}MB)`,
value: x
}));
},
listOptions() {
if (!this.selectedSchema || !this.selectedSchema.value) return {};
return {
data: () => {
return this.tableSchemas[this.selectedSchema.value]?.columns ?? [];
return this.tableSchemas?.[this.selectedSchema.value]?.columns ?? [];
},
hideControls: true,
columns: [
Expand Down Expand Up @@ -164,6 +194,18 @@ export default {
'runSQLQuery',
`SELECT * FROM \`${this.selectedSchema.value}\`;`
);
},
bytesToMB(bytes) {
return (bytes / (1024 * 1024)).toFixed(2);
},
preSelectSchema() {
if (!this.preSelectedSchema) return;
if (!this.tableSchemas) return;
if (this.autocompleteOptions.length == 0) return;
this.selectedSchema = {
label: this.preSelectedSchema,
value: this.preSelectedSchema
};
}
}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<template>
<Dialog
:options="{
title: 'Table Size',
size: '3xl'
}"
>
<template #body-content>
<ObjectList :options="listOptions" />
</template>
</Dialog>
</template>
<script>
import { h } from 'vue';
import ObjectList from '../../ObjectList.vue';
import { toast } from 'vue-sonner';
export default {
name: 'DatabaseTableSchemaSizeDetails',
props: {
site: {
type: String,
required: true
},
tableSchemas: {
type: Object,
required: true
},
viewSchemaDetails: {
type: Function,
required: true
}
},
components: {
ObjectList
},
computed: {
listOptions() {
if (!this.tableSchemas) return {};
let data = [];
for (const tableName in this.tableSchemas) {
const table = this.tableSchemas[tableName];
data.push({
table_name: tableName,
index_size: this.bytesToMB(table.size.index_length),
data_size: this.bytesToMB(table.size.data_length),
total_size: this.bytesToMB(table.size.total_size)
});
}
// sort in the order of total_size
data.sort((a, b) => b.total_size - a.total_size);
return {
data: () => data,
hideControls: true,
columns: [
{
label: 'Table Name',
fieldname: 'table_name',
width: '180px',
align: 'left',
type: 'Component',
component({ row }) {
return h(
'div',
{
class: 'truncate text-base cursor-copy',
onClick() {
if ('clipboard' in navigator) {
navigator.clipboard.writeText(row.table_name);
toast.success('Copied to clipboard');
}
}
},
[row.table_name]
);
}
},
{
label: 'Total Size (MB)',
fieldname: 'total_size',
align: 'center'
},
{
label: 'Data Size (MB)',
fieldname: 'data_size',
align: 'center'
},
{
label: 'Index Size (MB)',
fieldname: 'index_size',
align: 'center'
},
{
label: 'View Schema',
fieldname: 'table_name',
type: 'Component',
align: 'center',
component: ({ row }) => {
return h(
'button',
{
class:
'inline-flex items-center justify-center gap-2 transition-colors focus:outline-none text-gray-800 bg-gray-100 hover:bg-gray-200 active:bg-gray-300 focus-visible:ring focus-visible:ring-gray-400 h-7 text-base px-2 rounded',
onClick: () => {
this.viewSchemaDetails(row.table_name);
}
},
['View Schema']
);
}
}
]
};
}
},
methods: {
bytesToMB(bytes) {
return (bytes / (1024 * 1024)).toFixed(2);
}
}
};
</script>
50 changes: 43 additions & 7 deletions dashboard/src2/pages/devtools/database/DatabaseAnalyzer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,23 @@
Database Size Breakup
</p>
<div class="flex flex-row gap-2">
<Button @click="optimizeTable"> View Details </Button>
<Button @click="optimizeTable"> Optimize Table </Button>
<Button @click="this.showTableSchemaSizeDetailsDialog = true">
View Details
</Button>
<Button
@click="optimizeTable"
:loading="this.$resources.optimizeTable.loading"
>
Optimize Table
</Button>
</div>
</div>

<!-- TODO: Make it a separate component to reuse it -->
<!-- Slider -->
<div
class="mb-4 mt-4 flex h-7 w-full items-start justify-start overflow-clip rounded border bg-gray-50 pl-0"
class="mb-4 mt-4 flex h-7 w-full cursor-pointer items-start justify-start overflow-clip rounded border bg-gray-50 pl-0"
@click="showTableSchemaSizeDetailsDialog = true"
>
<div
class="h-7"
Expand Down Expand Up @@ -231,7 +239,21 @@
</FTabs>
</ToggleContent>

<!-- <ObjectList :options="tableAnalysisTableOptions" /> -->
<DatabaseTableSchemaSizeDetailsDialog
v-if="this.site"
:site="this.site"
:tableSchemas="tableSchemas"
v-model="showTableSchemaSizeDetailsDialog"
:viewSchemaDetails="viewTableSchemaDetails"
/>

<DatabaseTableSchemaDialog
v-if="this.site"
:site="this.site"
:tableSchemas="tableSchemas"
:pre-selected-schema="preSelectedSchemaForSchemaDialog"
v-model="showTableSchemasDialog"
/>
</div>
<div
v-else-if="!site"
Expand All @@ -257,6 +279,8 @@ import { toast } from 'vue-sonner';
import ToggleContent from '../../../components/ToggleContent.vue';
import ResultTable from '../../../components/devtools/database/ResultTable.vue';
import DatabaseProcessKillButton from '../../../components/devtools/database/DatabaseProcessKillButton.vue';
import DatabaseTableSchemaDialog from '../../../components/devtools/database/DatabaseTableSchemaDialog.vue';
import DatabaseTableSchemaSizeDetailsDialog from '../../../components/devtools/database/DatabaseTableSchemaSizeDetailsDialog.vue';
export default {
name: 'DatabaseAnalyzer',
Expand All @@ -268,16 +292,20 @@ export default {
ObjectList,
ToggleContent,
ResultTable,
DatabaseTableSchemaDialog,
DatabaseTableSchemaSizeDetailsDialog,
DatabaseProcessKillButton
},
data() {
return {
site: null,
errorMessage: null,
optimizeTableJobName: null,
isIndexSuggestionTriggered: false,
queryTabIndex: 0,
dbIndexTabIndex: 0,
showTableSchemaSizeDetailsDialog: false,
preSelectedSchemaForSchemaDialog: null,
showTableSchemasDialog: false,
DatabaseProcessKillButton: markRaw(DatabaseProcessKillButton)
};
},
Expand Down Expand Up @@ -327,10 +355,12 @@ export default {
if (data?.message) {
if (data?.message?.success) {
toast.success(data?.message?.message);
this.$router.push(
`/sites/${this.site}/insights/jobs/${data?.message?.job_name}`
);
} else {
toast.error(data?.message?.message);
}
this.optimizeTableJobName = data?.message?.job_name;
}
}
};
Expand Down Expand Up @@ -392,7 +422,8 @@ export default {
},
tableSchemas() {
if (!this.isRequiredInformationReceived) return [];
return this.$resources.tableSchemas?.data?.message?.data;
let result = this.$resources.tableSchemas?.data?.message?.data ?? [];
return result;
},
tableSizeInfo() {
if (!this.isRequiredInformationReceived) return [];
Expand Down Expand Up @@ -615,6 +646,11 @@ export default {
dn: this.site,
method: 'optimize_tables'
});
},
viewTableSchemaDetails(tableName) {
this.showTableSchemaSizeDetailsDialog = false;
this.preSelectedSchemaForSchemaDialog = tableName;
this.showTableSchemasDialog = true;
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
:site="this.site"
:tableSchemas="$resources.tableSchemas?.data?.message?.data ?? {}"
v-model="showTableSchemasDialog"
:showSQLActions="true"
@runSQLQuery="runSQLQueryForViewingTable"
/>
</div>
Expand Down
24 changes: 13 additions & 11 deletions press/press/doctype/site/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -2267,23 +2267,25 @@ def get_update_information(self):
out.update_available = any([app["update_available"] for app in out.apps])
return out

def fetch_running_optimize_tables_job(self):
return frappe.db.exists(

Check warning on line 2271 in press/press/doctype/site/site.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/site/site.py#L2271

Added line #L2271 was not covered by tests
"Agent Job",
{
"site": self.name,
"job_type": "Optimize Tables",
"status": ["in", ["Undelivered", "Running", "Pending"]],
},
)

@dashboard_whitelist()
def optimize_tables(self, ignore_checks: bool = False):
if not ignore_checks:

Check warning on line 2282 in press/press/doctype/site/site.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/site/site.py#L2282

Added line #L2282 was not covered by tests
# check for running `Optimize Tables` agent job
existed_agent_job_name = frappe.db.exists(
"Agent Job",
{
"site": self.name,
"job_type": "Optimize Tables",
"status": ["in", ["Undelivered", "Running", "Pending"]],
},
)
if existed_agent_job_name:
if job := self.fetch_running_optimize_tables_job():
return {

Check warning on line 2285 in press/press/doctype/site/site.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/site/site.py#L2284-L2285

Added lines #L2284 - L2285 were not covered by tests
"success": True,
"message": "Optimize Tables job is already running on this site.",
"job_name": existed_agent_job_name,
"job_name": job,
}
# check if `Optimize Tables` has run in last 1 hour
recent_agent_job_name = frappe.db.exists(

Check warning on line 2291 in press/press/doctype/site/site.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/site/site.py#L2291

Added line #L2291 was not covered by tests
Expand All @@ -2298,7 +2300,7 @@ def optimize_tables(self, ignore_checks: bool = False):
if recent_agent_job_name:
return {

Check warning on line 2301 in press/press/doctype/site/site.py

View check run for this annotation

Codecov / codecov/patch

press/press/doctype/site/site.py#L2300-L2301

Added lines #L2300 - L2301 were not covered by tests
"success": False,
"message": "Optimize Tables job has already run in the last 1 hour.",
"message": "Optimize Tables job has already run in the last 1 hour. Try later.",
"job_name": None,
}

Expand Down

0 comments on commit 5ae9332

Please sign in to comment.