forked from github-mirror/CoreProtect
Improved MySQL index handling (fixes #867)
This commit is contained in:
1 parent
ff36b6e0e6
commit
d69fffbce0
2 files changed
+108
-9
No files matched your search
@@ -12,6 +12,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -326,6 +327,7 @@ public class Database extends Queue {
|
||||
if (connection != null) {
|
||||
Statement statement = connection.createStatement();
|
||||
createMySQLTableStructures(prefix, statement);
|
||||
createMySQLIndexes(prefix, statement, purge);
|
||||
if (!purge && forceConnection == null) {
|
||||
initializeTables(prefix, statement);
|
||||
}
|
||||
@@ -413,6 +415,103 @@ public class Database extends Queue {
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "world(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,world varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
}
|
||||
|
||||
private static void createMySQLIndexes(String prefix, Statement statement, boolean purge) {
|
||||
try {
|
||||
ensureMySQLIndex(statement, prefix + "block", "wid", "x", "z", "time");
|
||||
ensureMySQLIndex(statement, prefix + "block", "user", "time");
|
||||
ensureMySQLIndex(statement, prefix + "block", "type", "time");
|
||||
ensureMySQLIndex(statement, prefix + "container", "wid", "x", "z", "time");
|
||||
ensureMySQLIndex(statement, prefix + "container", "user", "time");
|
||||
ensureMySQLIndex(statement, prefix + "container", "type", "time");
|
||||
ensureMySQLIndex(statement, prefix + "item", "wid", "x", "z", "time");
|
||||
ensureMySQLIndex(statement, prefix + "item", "user", "time");
|
||||
ensureMySQLIndex(statement, prefix + "item", "type", "time");
|
||||
}
|
||||
catch (Exception e) {
|
||||
Chat.console(Phrase.build(Phrase.DATABASE_INDEX_ERROR));
|
||||
if (purge) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ensureMySQLIndex(Statement statement, String tableName, String... columns) throws SQLException {
|
||||
if (hasMySQLIndex(statement, tableName, columns)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String indexName = createMySQLIndexName(tableName, columns);
|
||||
String indexColumns = String.join(",", columns);
|
||||
statement.executeUpdate("CREATE INDEX " + indexName + " ON " + tableName + "(" + indexColumns + ")");
|
||||
}
|
||||
|
||||
private static boolean hasMySQLIndex(Statement statement, String tableName, String... columns) {
|
||||
Map<String, TreeMap<Integer, String>> indexData = new HashMap<>();
|
||||
|
||||
try (ResultSet resultSet = statement.executeQuery("SHOW INDEX FROM " + tableName)) {
|
||||
while (resultSet.next()) {
|
||||
String keyName = resultSet.getString("Key_name");
|
||||
int sequence = resultSet.getInt("Seq_in_index");
|
||||
String columnName = resultSet.getString("Column_name");
|
||||
if (keyName == null || columnName == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
indexData.computeIfAbsent(keyName, key -> new TreeMap<>()).put(sequence, columnName.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<String> expected = new ArrayList<>(columns.length);
|
||||
for (String column : columns) {
|
||||
expected.add(column.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
for (TreeMap<Integer, String> indexColumns : indexData.values()) {
|
||||
if (indexColumns.size() < expected.size()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean matchesPrefix = true;
|
||||
int position = 0;
|
||||
for (String column : indexColumns.values()) {
|
||||
if (!column.equals(expected.get(position))) {
|
||||
matchesPrefix = false;
|
||||
break;
|
||||
}
|
||||
position++;
|
||||
if (position == expected.size()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (matchesPrefix && position == expected.size()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String createMySQLIndexName(String tableName, String... columns) {
|
||||
String normalizedTable = tableName.replaceAll("[^A-Za-z0-9_]", "_");
|
||||
String joinedColumns = String.join("_", columns);
|
||||
String candidate = normalizedTable + "_" + joinedColumns + "_idx";
|
||||
if (candidate.length() <= 64) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
String hash = Integer.toHexString(candidate.hashCode());
|
||||
int maxPrefixLength = 64 - (hash.length() + 1);
|
||||
if (maxPrefixLength < 1) {
|
||||
maxPrefixLength = 1;
|
||||
}
|
||||
|
||||
return candidate.substring(0, maxPrefixLength) + "_" + hash;
|
||||
}
|
||||
|
||||
private static void createSQLiteTables(String prefix, boolean forcePrefix, Connection forceConnection, boolean purge) {
|
||||
try (Connection connection = (forceConnection != null ? forceConnection : Database.getConnection(true, 0))) {
|
||||
Statement statement = connection.createStatement();
|
||||
|
||||
@@ -586,17 +586,17 @@ public class LookupRaw extends Queue {
|
||||
String unionSelect = "SELECT * FROM (";
|
||||
if (Config.getGlobal().MYSQL) {
|
||||
if (queryTable.equals("block")) {
|
||||
if (includeBlock.length() > 0 || includeEntity.length() > 0) {
|
||||
index = "USE INDEX(type) IGNORE INDEX(user,wid) ";
|
||||
}
|
||||
if (users.length() > 0) {
|
||||
index = "USE INDEX(user) IGNORE INDEX(type,wid) ";
|
||||
}
|
||||
if (radius != null && (radius[2] - radius[1]) <= 50 && (radius[6] - radius[5]) <= 50) {
|
||||
index = "USE INDEX(wid) IGNORE INDEX(type,user) ";
|
||||
index = "USE INDEX(wid) ";
|
||||
}
|
||||
if ((restrictWorld && (users.length() > 0 || includeBlock.length() > 0 || includeEntity.length() > 0))) {
|
||||
index = "IGNORE INDEX(PRIMARY) ";
|
||||
else if (users.length() > 0) {
|
||||
index = "USE INDEX(user) ";
|
||||
}
|
||||
else if (includeBlock.length() > 0 || includeEntity.length() > 0) {
|
||||
index = "USE INDEX(type) ";
|
||||
}
|
||||
else if (restrictWorld) {
|
||||
index = "USE INDEX(wid) ";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user