public boolean saveHighScore(Client c) throws SQLException {
long totallvlexp = (long) (c.playerXP[0]) + (c.playerXP[1]) + (c.playerXP[2]) + (c.playerXP[3]) + (c.playerXP[4]) + (c.playerXP[5]) + (c.playerXP[6]) + (c.playerXP[7]) + (c.playerXP[8]) + (c.playerXP[9]) + (c.playerXP[10]) + (c.playerXP[11]) + (c.playerXP[12]) + (c.playerXP[13]) + (c.playerXP[14]) + (c.playerXP[15]) + (c.playerXP[16]) + (c.playerXP[17]) + (c.playerXP[18]) + (c.playerXP[19]) + (c.playerXP[20]);
int totallevell = (int) (c.getLevelForXP(c.playerXP[0]) + c.getLevelForXP(c.playerXP[1]) + c.getLevelForXP(c.playerXP[2]) + c.getLevelForXP(c.playerXP[3]) + c.getLevelForXP(c.playerXP[4]) + c.getLevelForXP(c.playerXP[5]) + c.getLevelForXP(c.playerXP[6]) + c.getLevelForXP(c.playerXP[7]) + c.getLevelForXP(c.playerXP[8]) + c.getLevelForXP(c.playerXP[9]) + c.getLevelForXP(c.playerXP[10]) + c.getLevelForXP(c.playerXP[11]) + c.getLevelForXP(c.playerXP[12]) + c.getLevelForXP(c.playerXP[13]) + c.getLevelForXP(c.playerXP[14]) + c.getLevelForXP(c.playerXP[15]) + c.getLevelForXP(c.playerXP[16]) + c.getLevelForXP(c.playerXP[17]) + c.getLevelForXP(c.playerXP[18]) + c.getLevelForXP(c.playerXP[19]) + c.getLevelForXP(c.playerXP[20]));
String delQuery1 = "DELETE FROM `skills` WHERE playerName = '"+c.playerName+"';";
String delQuery2 = "DELETE FROM `skillsoverall` WHERE playerName = '"+c.playerName+"';";
String delQuery3 = "DELETE FROM `playerrights` WHERE playerName = '"+c.playerName+"';";
String insQuery1 = "INSERT INTO `skills` (`playerName`,`Attacklvl`,`Attackxp`,`Defencelvl`,`Defencexp`,`Strengthlvl`,`Strengthxp`,`Hitpointslvl`,`Hitpointsxp`,`Rangelvl`,`Rangexp`,`Prayerlvl`,`Prayerxp`,`Magiclvl`,`Magicxp`,`Cookinglvl`,`Cookingxp`,`Woodcuttinglvl`,`Woodcuttingxp`,`Fletchinglvl`,`Fletchingxp`,`Fishinglvl`,`Fishingxp`,`Firemakinglvl`,`Firemakingxp`,`Craftinglvl`,`Craftingxp`,`Smithinglvl`,`Smithingxp`,`Mininglvl`,`Miningxp`,`Herblorelvl`,`Herblorexp`,`Agilitylvl`,`Agilityxp`,`Thievinglvl`,`Thievingxp`,`Slayerlvl`,`Slayerxp`,`Farminglvl`,`Farmingxp`,`Runecraftlvl`,`Runecraftxp`) VALUES ('"+c.playerName+"',"+c.playerLevel[0]+","+c.playerXP[0]+","+c.playerLevel[1]+","+c.playerXP[1]+","+c.playerLevel[2]+","+c.playerXP[2]+","+c.playerLevel[3]+","+c.playerXP[3]+","+c.playerLevel[4]+","+c.playerXP[4]+","+c.playerLevel[5]+","+c.playerXP[5]+","+c.playerLevel[6]+","+c.playerXP[6]+","+c.playerLevel[7]+","+c.playerXP[7]+","+c.playerLevel[8]+","+c.playerXP[8]+","+c.playerLevel[9]+","+c.playerXP[9]+","+c.playerLevel[10]+","+c.playerXP[10]+","+c.playerLevel[11]+","+c.playerXP[11]+","+c.playerLevel[12]+","+c.playerXP[12]+","+c.playerLevel[13]+","+c.playerXP[13]+","+c.playerLevel[14]+","+c.playerXP[14]+","+c.playerLevel[15]+","+c.playerXP[15]+","+c.playerLevel[16]+","+c.playerXP[16]+","+c.playerLevel[17]+","+c.playerXP[17]+","+c.playerLevel[18]+","+c.playerXP[18]+","+c.playerLevel[19]+","+c.playerXP[19]+","+c.playerLevel[20]+","+c.playerXP[20]+");";
String insQuery2 = "INSERT INTO `skillsoverall` (`playerName`,`lvl`,`xp`) VALUES ('"+c.playerName+"',"+totallevell+","+totallvlexp+");";
String insQuery3 = "INSERT INTO `playerrights` (`playerName`,`rank`) VALUES ('"+c.playerName+"',"+c.playerRights+");";
String[] delQueries = {delQuery1, delQuery2, delQuery3};
String[] insQueries = {insQuery1, insQuery2, insQuery3};
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
try(Connection conX = DriverManager.getConnection("jdbc:mysql://localhost/highscores","root","root")) {
try(Statement stmtX = conX.createStatement()) {
for(int i = 0; i < delQueries.length; i++)
{
stmtX.executeUpdate(delQueries[i]);
stmtX.executeUpdate(insQueries[i]);
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
}
使用此代码我怎样才能让它更快?如果我使用UPDATE而不是它会更快?如果它会请我告诉我如何使用我提供的代码。我对SQL不太满意,只是帮助了一位朋友。
答案 0 :(得分:2)
改善这种情况的一些方法:
UPDATE
语句并使用WHERE
子句中主键的值。这是为了你知道id。如果你不知道,那么UPDATE
语句。在将用于WHERE
子句的列上添加适当的索引,如果是单个列且它不是主键,则此语句可能会多次执行。Connection#setAutoCommit(false);
开始交易,然后使用Connection#commit
关闭它。如果出现错误,请使用Connection#rollback()
,并且所有操作都不会影响数据库。Statement
。如果您的查询需要参数化,请改用PreparedStatement
。在您的数据库中,执行以下操作:
ALTER TABLE skills ADD INDEX idx_playerName (playerName);
以下是使用上述语句更新的Java代码的一部分:
public boolean saveHighScore(Client c) throws SQLException {
long totallvlexp = (long) (c.playerXP[0]) + (c.playerXP[1]) + (c.playerXP[2]) + (c.playerXP[3]) + (c.playerXP[4]) + (c.playerXP[5]) + (c.playerXP[6]) + (c.playerXP[7]) + (c.playerXP[8]) + (c.playerXP[9]) + (c.playerXP[10]) + (c.playerXP[11]) + (c.playerXP[12]) + (c.playerXP[13]) + (c.playerXP[14]) + (c.playerXP[15]) + (c.playerXP[16]) + (c.playerXP[17]) + (c.playerXP[18]) + (c.playerXP[19]) + (c.playerXP[20]);
int totallevell = (int) (c.getLevelForXP(c.playerXP[0]) + c.getLevelForXP(c.playerXP[1]) + c.getLevelForXP(c.playerXP[2]) + c.getLevelForXP(c.playerXP[3]) + c.getLevelForXP(c.playerXP[4]) + c.getLevelForXP(c.playerXP[5]) + c.getLevelForXP(c.playerXP[6]) + c.getLevelForXP(c.playerXP[7]) + c.getLevelForXP(c.playerXP[8]) + c.getLevelForXP(c.playerXP[9]) + c.getLevelForXP(c.playerXP[10]) + c.getLevelForXP(c.playerXP[11]) + c.getLevelForXP(c.playerXP[12]) + c.getLevelForXP(c.playerXP[13]) + c.getLevelForXP(c.playerXP[14]) + c.getLevelForXP(c.playerXP[15]) + c.getLevelForXP(c.playerXP[16]) + c.getLevelForXP(c.playerXP[17]) + c.getLevelForXP(c.playerXP[18]) + c.getLevelForXP(c.playerXP[19]) + c.getLevelForXP(c.playerXP[20]));
boolean result = true;
String updateSkillsSql = "UPDATE skills"
+ " SET `Attacklvl`=?,"
+ " `Attackxp`=?,"
+ " `Defencelvl`=?,"
+ " `Defencexp`=?,"
+ " `Strengthlvl`=?,"
+ " `Strengthxp`=?,"
+ " `Hitpointslvl`=?,"
+ " `Hitpointsxp`=?,"
+ " `Rangelvl`=?,"
+ " `Rangexp`=?,"
+ " `Prayerlvl`=?,"
+ " `Prayerxp`=?,"
+ " `Magiclvl`=?,"
+ " `Magicxp`=?,"
+ " `Cookinglvl`=?,"
+ " `Cookingxp`=?,"
+ " `Woodcuttinglvl`=?,"
+ " `Woodcuttingxp`=?,"
+ " `Fletchinglvl`=?,"
+ " `Fletchingxp`=?,"
+ " `Fishinglvl`=?,"
+ " `Fishingxp`=?,"
+ " `Firemakinglvl`=?,"
+ " `Firemakingxp`=?,"
+ " `Craftinglvl`=?,"
+ " `Craftingxp`=?,"
+ " `Smithinglvl`=?,"
+ " `Smithingxp`=?,"
+ " `Mininglvl`=?,"
+ " `Miningxp`=?,"
+ " `Herblorelvl`=?,"
+ " `Herblorexp`=?,"
+ " `Agilitylvl`=?,"
+ " `Agilityxp`=?,"
+ " `Thievinglvl`=?,"
+ " `Thievingxp`=?,"
+ " `Slayerlvl`=?,"
+ " `Slayerxp`=?,"
+ " `Farminglvl`=?,"
+ " `Farmingxp`=?,"
+ " `Runecraftlvl`=?,"
+ " `Runecraftxp`=?"
+ " WHERE playerName = ?";
//do similar for the other queries...
//not needed since JDBC 4, noted since you're using Java 7
//Class.forName("com.mysql.jdbc.Driver").newInstance();
try(Connection con = DriverManager.getConnection("jdbc:mysql://localhost/highscores","root","root")) {
//when storing multiple data, it's better to use a transaction
con.setAutoCommit(false);
try(PreparedStatement pstmt = con.prepareStatement(updateSkillsSql);
//declare the other PreparedStatements for each update sql statement here...
) {
//do something like this for every PreparedStatement
setParameters(pstmt,
c.playerLevel[0], c.playerXP[0],
c.playerLevel[1], c.playerXP[1],
c.playerLevel[2], c.playerXP[2],
c.playerLevel[3], c.playerXP[3],
c.playerLevel[4], c.playerXP[4],
c.playerLevel[5], c.playerXP[5],
c.playerLevel[6], c.playerXP[6],
c.playerLevel[7], c.playerXP[7],
c.playerLevel[8], c.playerXP[8],
c.playerLevel[9], c.playerXP[9],
c.playerLevel[10], c.playerXP[10],
c.playerLevel[11], c.playerXP[11],
c.playerLevel[12], c.playerXP[12],
c.playerLevel[13], c.playerXP[13],
c.playerLevel[14], c.playerXP[14],
c.playerLevel[15], c.playerXP[15],
c.playerLevel[16], c.playerXP[16],
c.playerLevel[17], c.playerXP[17],
c.playerLevel[18], c.playerXP[18],
c.playerLevel[19], c.playerXP[19],
c.playerLevel[20], c.playerXP[20],
c.playerName);
pstmt.executeUpdate();
} catch (Exception e) {
System.out.println(String.format("There's a problem when saving the data of player %s.", c.playerName));
e.printStackTrace(System.out);
con.rollback();
result = false;
}
if (result) {
con.commit();
con.setAutoCommit(true);
}
} catch (Exception e) {
System.out.println(String.format("There's a problem when saving the data of player %s.", c.playerName));
e.printStackTrace(System.out);
result = false;
}
return result;
}
//created method to add parameters despite its type
private void setParameters(PreparedStatement pstmt, Object ... args) {
int i = 1;
for (Object arg : args) {
pstmt.setObject(i++, arg);
}
}
答案 1 :(得分:0)
DELETE
/ INSERT
方法或UPDATE
方法中的最大费用可能是您的WHERE
条款。
执行UPDATE
或DELETE
,WHERE
指向playerName = 'FriendlyNameOfPlayer'
是残酷的。如果在该字段上创建索引,则可以使其更好一些。
您可以使用......的某些内容创建索引。
CREATE INDEX playerName_ix ON skills (playerName)
CREATE INDEX playerName_ix ON skillsoverall (playerName)
详细了解可能与具体情况相关的其他一些选项here。
更好的做法是按行PK
(可能是自动递增的整数?)来定位行。理想情况下,这背后的架构将是一个名为Player_Master
的表,其自动递增整数为PK
,然后是另一列中存储的播放器的友好名称。像代码snippit中引用的那些表应该存储来自Player_Master
的PK值(而不是友好名称),这将是FK
&#39; s。您的DELETE
语句看起来就像......
DELETE FROM `skills` WHERE skills.playerID = 37
重做架构将是&#34;正确的&#34;这样做的方法,但我得知每个项目可能没有完全拆解/重做所需的时间或资源。如果你的好友说'#34;你能让这个更快吗?&#34;,你可以做索引并走开。如果问题是&#34;我该如何做到这一点?&#34;,我会在计费时间开始计时,因为从提供的代码和架构的小瞥看,它不是快速解决。
我还会因为调用拼凑在一起的TSQL语句的原始执行而嘲笑你。有更好的方法来做到这一点。