mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-28 17:01:14 +00:00
perf(esx_multicharacter): index the columns used by character deletion
Deleting a character runs one DELETE per table that has an identifier/owner column, all in a single transaction. Only users.identifier is indexed; the other core tables (billing, owned_vehicles, user_licenses, society_moneywash, addon_account_data, addon_inventory_items, datastore_data) have no usable index on the delete column, so each DELETE is a full table scan and they all hold locks at once. Measured on 200k rows per table (MariaDB 12.3.2): the transaction went from about 1573 ms to about 22 ms once the seven columns are indexed, EXPLAIN going from type=ALL scanning ~200k rows to a single-row index lookup per table. The addon and datastore tables were the worst because their composite indexes do not lead with the delete column, so they cannot serve WHERE owner = ?. Adds the indexes to legacy.sql for fresh installs and a migration for existing databases. The migration checks INFORMATION_SCHEMA for an index that leads with the column (SEQ_IN_INDEX = 1) and only creates one where it is missing, so it is a no-op on databases that already have it and re-running is guarded by the migration key.
This commit is contained in:
+14
-7
@@ -749,7 +749,8 @@ ALTER TABLE `addon_account`
|
|||||||
ALTER TABLE `addon_account_data`
|
ALTER TABLE `addon_account_data`
|
||||||
ADD PRIMARY KEY (`id`),
|
ADD PRIMARY KEY (`id`),
|
||||||
ADD UNIQUE KEY `index_addon_account_data_account_name_owner` (`account_name`,`owner`),
|
ADD UNIQUE KEY `index_addon_account_data_account_name_owner` (`account_name`,`owner`),
|
||||||
ADD KEY `index_addon_account_data_account_name` (`account_name`);
|
ADD KEY `index_addon_account_data_account_name` (`account_name`),
|
||||||
|
ADD KEY `esx_addon_account_data_owner` (`owner`);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Indexes for table `addon_inventory`
|
-- Indexes for table `addon_inventory`
|
||||||
@@ -764,13 +765,15 @@ ALTER TABLE `addon_inventory_items`
|
|||||||
ADD PRIMARY KEY (`id`),
|
ADD PRIMARY KEY (`id`),
|
||||||
ADD KEY `index_addon_inventory_items_inventory_name_name` (`inventory_name`,`name`),
|
ADD KEY `index_addon_inventory_items_inventory_name_name` (`inventory_name`,`name`),
|
||||||
ADD KEY `index_addon_inventory_items_inventory_name_name_owner` (`inventory_name`,`name`,`owner`),
|
ADD KEY `index_addon_inventory_items_inventory_name_name_owner` (`inventory_name`,`name`,`owner`),
|
||||||
ADD KEY `index_addon_inventory_inventory_name` (`inventory_name`);
|
ADD KEY `index_addon_inventory_inventory_name` (`inventory_name`),
|
||||||
|
ADD KEY `esx_addon_inventory_items_owner` (`owner`);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Indexes for table `billing`
|
-- Indexes for table `billing`
|
||||||
--
|
--
|
||||||
ALTER TABLE `billing`
|
ALTER TABLE `billing`
|
||||||
ADD PRIMARY KEY (`id`);
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `esx_billing_identifier` (`identifier`);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Indexes for table `cardealer_vehicles`
|
-- Indexes for table `cardealer_vehicles`
|
||||||
@@ -790,7 +793,8 @@ ALTER TABLE `datastore`
|
|||||||
ALTER TABLE `datastore_data`
|
ALTER TABLE `datastore_data`
|
||||||
ADD PRIMARY KEY (`id`),
|
ADD PRIMARY KEY (`id`),
|
||||||
ADD UNIQUE KEY `index_datastore_data_name_owner` (`name`,`owner`),
|
ADD UNIQUE KEY `index_datastore_data_name_owner` (`name`,`owner`),
|
||||||
ADD KEY `index_datastore_data_name` (`name`);
|
ADD KEY `index_datastore_data_name` (`name`),
|
||||||
|
ADD KEY `esx_datastore_data_owner` (`owner`);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Indexes for table `items`
|
-- Indexes for table `items`
|
||||||
@@ -821,7 +825,8 @@ ALTER TABLE `licenses`
|
|||||||
-- Indexes for table `owned_vehicles`
|
-- Indexes for table `owned_vehicles`
|
||||||
--
|
--
|
||||||
ALTER TABLE `owned_vehicles`
|
ALTER TABLE `owned_vehicles`
|
||||||
ADD PRIMARY KEY (`plate`);
|
ADD PRIMARY KEY (`plate`),
|
||||||
|
ADD KEY `esx_owned_vehicles_owner` (`owner`);
|
||||||
|
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
@@ -840,7 +845,8 @@ ALTER TABLE `rented_vehicles`
|
|||||||
-- Indexes for table `society_moneywash`
|
-- Indexes for table `society_moneywash`
|
||||||
--
|
--
|
||||||
ALTER TABLE `society_moneywash`
|
ALTER TABLE `society_moneywash`
|
||||||
ADD PRIMARY KEY (`id`);
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `esx_society_moneywash_identifier` (`identifier`);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Indexes for table `users`
|
-- Indexes for table `users`
|
||||||
@@ -856,7 +862,8 @@ ALTER TABLE `users`
|
|||||||
-- Indexes for table `user_licenses`
|
-- Indexes for table `user_licenses`
|
||||||
--
|
--
|
||||||
ALTER TABLE `user_licenses`
|
ALTER TABLE `user_licenses`
|
||||||
ADD PRIMARY KEY (`id`);
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `esx_user_licenses_owner` (`owner`);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Indexes for table `vehicle_categories`
|
-- Indexes for table `vehicle_categories`
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
local esxVersion = "v1.14.2"
|
||||||
|
|
||||||
|
Core.Migrations = Core.Migrations or {}
|
||||||
|
Core.Migrations[esxVersion] = Core.Migrations[esxVersion] or {}
|
||||||
|
|
||||||
|
if GetResourceKvpInt(("esx_migration:%s"):format(esxVersion)) == 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local targets = {
|
||||||
|
{ table = "billing", column = "identifier" },
|
||||||
|
{ table = "owned_vehicles", column = "owner" },
|
||||||
|
{ table = "user_licenses", column = "owner" },
|
||||||
|
{ table = "society_moneywash", column = "identifier" },
|
||||||
|
{ table = "addon_account_data", column = "owner" },
|
||||||
|
{ table = "addon_inventory_items", column = "owner" },
|
||||||
|
{ table = "datastore_data", column = "owner" },
|
||||||
|
}
|
||||||
|
|
||||||
|
---@return boolean restartRequired
|
||||||
|
Core.Migrations[esxVersion].multicharDeleteIndexes = function()
|
||||||
|
print("^4[esx_migration:v1.14.2:multicharDeleteIndexes]^7 Indexing character deletion columns.")
|
||||||
|
|
||||||
|
for i = 1, #targets do
|
||||||
|
local target = targets[i]
|
||||||
|
|
||||||
|
local tableExists = MySQL.scalar.await([[
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.TABLES
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = ?
|
||||||
|
]], { target.table })
|
||||||
|
|
||||||
|
if tableExists ~= 0 then
|
||||||
|
local leadingIndex = MySQL.scalar.await([[
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM INFORMATION_SCHEMA.STATISTICS
|
||||||
|
WHERE TABLE_SCHEMA = DATABASE()
|
||||||
|
AND TABLE_NAME = ?
|
||||||
|
AND COLUMN_NAME = ?
|
||||||
|
AND SEQ_IN_INDEX = 1
|
||||||
|
]], { target.table, target.column })
|
||||||
|
|
||||||
|
if leadingIndex == 0 then
|
||||||
|
MySQL.update.await(("CREATE INDEX `esx_%s_%s` ON `%s` (`%s`)"):format(target.table, target.column, target.table, target.column))
|
||||||
|
print(("^4[esx_migration:v1.14.2:multicharDeleteIndexes]^7 Indexed ^5%s.%s^7."):format(target.table, target.column))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print("^4[esx_migration:v1.14.2:multicharDeleteIndexes]^7 Migration complete.")
|
||||||
|
return false
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user