如何优化此数据库布局MySQL

时间:2017-05-08 21:42:36

标签: mysql database

我正在尝试为我正在处理的游戏服务器优化保存和加载。当前表格如下(该表格是在3年前创建的,当时我加入了这个团队之前):

enter image description here

show create table如下所示:

CREATE TABLE `inventoryitems` (
  `inventoryitemid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `type` tinyint(3) unsigned NOT NULL,
  `characterid` int(11) DEFAULT NULL,
  `accountid` int(11) DEFAULT NULL,
  `itemid` int(11) NOT NULL DEFAULT '0',
  `inventorytype` int(11) NOT NULL DEFAULT '0',
  `position` int(11) NOT NULL DEFAULT '0',
  `quantity` int(11) NOT NULL DEFAULT '0',
  `owner` tinytext NOT NULL,
  `petid` int(11) NOT NULL DEFAULT '-1',
  `flag` int(11) NOT NULL,
  `expiration` bigint(20) NOT NULL DEFAULT '-1',
  `giftFrom` varchar(26) NOT NULL,
  PRIMARY KEY (`inventoryitemid`),
  KEY `CHARID` (`characterid`),
  KEY `inventorytype` (`inventorytype`),
  KEY `type` (`type`),
  KEY `accountid` (`accountid`)
) ENGINE=InnoDB AUTO_INCREMENT=79599139 DEFAULT CHARSET=latin1

正如您所看到的,此表上有5个索引,这大大减慢了存储速度。详细说明索引:

  • InventoryItemID :在保存项目被视为设备的实例中用于InventoryEquipment的主索引。
  • characterid:将项目与所有者的角色ID相关联的重要索引
  • inventorytype :此索引用于确定项目转到哪个广告资源标签。有几个选项卡,例如 EQUIP,USE,ETC 。存在的原因是为了防止物品在它们不应该被加载到同一个槽中时。这是一个示例图像。

    enter image description here

如您所见,有五个不同的标签。每个标签都有插入项目的插槽。 inventorytype将项目分隔到这些区域。

  • 类型:确定这是什么类型的保存。在游戏中,这种贬低3种不同的类别。 商家商品存储商品库存商品。此类型确定项目如何加载到游戏中。当角色登录时,将加载库存项目。存储项目在通过存储访问项目时会加载。当玩家通过Merchant存储访问商家商品时,会加载商家商品。
  • accountid :存储项目通过存储进行链接。它们是通过帐户而不是字符链接的唯一项目

思考:我觉得这个表可以被截断。由于它仅用于存储,所以甚至经常使用accountid,因此必须使用索引来保持较小的加载时间,但确实会损害保存。此外,商家商品不会被插槽保存,因此将它们放在这里是没有意义的。

解决方案:将它们分成3个不同的表格。 问题:怎么样?下面是我如何尝试拆分它们的图片,但仍有问题。

enter image description here

我不知道这种布局是否可行,因为顶层(帐户,商家,库存)首先插入,但需要来自第二层(项目)的密钥。有没有更好的方法解决这个问题?或者我只是看错了?

这是我在Java中的代码(游戏在Java上运行),它执行数据库调用以保存:

public synchronized void saveItems(List<Pair<Item, MapleInventoryType>> items, int id, Connection con) throws SQLException {
        lock.lock();
        long start = System.currentTimeMillis();
        StringBuilder query = new StringBuilder();
        query.append(
                "DELETE `inventoryitems`, `inventoryequipment` FROM `inventoryitems` LEFT JOIN `inventoryequipment` USING(`inventoryitemid`) WHERE `type` = ? AND `");
        query.append(account ? "accountid" : "characterid").append("` = ?");
        try {
            try (PreparedStatement ps = con.prepareStatement(query.toString())) {
                ps.setInt(1, value);
                ps.setInt(2, id);
                ps.executeUpdate();
            }
            try (PreparedStatement ps = con.prepareStatement("INSERT INTO `inventoryitems` VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
                 Statement.RETURN_GENERATED_KEYS);
                 PreparedStatement pse = con.prepareStatement(
                 "INSERT INTO `inventoryequipment` VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) {
                LinkedList<Pair<Item, MapleInventoryType>> saved_items = new LinkedList<>();

                if (!items.isEmpty()) {
                    for (Pair<Item, MapleInventoryType> pair : items) {
                        Item item = pair.getLeft();
                        if (item.disappearsAtLogout())
                            continue;
                        MapleInventoryType mit = pair.getRight();
                        ps.setInt(1, value);
                        ps.setString(2, account ? null : String.valueOf(id));
                        ps.setString(3, account ? String.valueOf(id) : null);
                        ps.setInt(4, item.getItemId());
                        ps.setInt(5, mit.getType());
                        ps.setInt(6, item.getPosition());
                        ps.setInt(7, item.getQuantity());
                        ps.setString(8, item.getOwner());
                        ps.setInt(9, item.getPetId());
                        ps.setInt(10, item.getFlag());
                        ps.setLong(11, item.getExpiration());
                        ps.setString(12, item.getGiftFrom());
                        saved_items.add(pair);
                        ps.addBatch();
                    }

                    ps.executeBatch();

                    try (ResultSet rs = ps.getGeneratedKeys()) {
                        for (Pair<Item, MapleInventoryType> item : saved_items) {
                            int key = -1;
                            if (rs.next()) {                            
                                key = rs.getInt(1);
                            } else {
                                key = item.getLeft().getInventoryItemId();
                            }
                            MapleInventoryType mit = item.right; 
                            if (mit.equals(MapleInventoryType.EQUIP) || mit.equals(MapleInventoryType.EQUIPPED)) {
                                pse.setInt(1, key);
                                Equip equip = (Equip) item.left;
                                pse.setInt(2, equip.getUpgradeSlots());
                                pse.setInt(3, equip.getLevel());
                                pse.setInt(4, equip.getStr());
                                pse.setInt(5, equip.getDex());
                                pse.setInt(6, equip.getInt());
                                pse.setInt(7, equip.getLuk());
                                pse.setInt(8, equip.getHp());
                                pse.setInt(9, equip.getMp());
                                pse.setInt(10, equip.getWatk());
                                pse.setInt(11, equip.getMatk());
                                pse.setInt(12, equip.getWdef());
                                pse.setInt(13, equip.getMdef());
                                pse.setInt(14, equip.getAcc());
                                pse.setInt(15, equip.getAvoid());
                                pse.setInt(16, equip.getHands());
                                pse.setInt(17, equip.getSpeed());
                                pse.setInt(18, equip.getJump());
                                pse.setInt(19, equip.getVicious());
                                pse.setInt(20, equip.getItemLevel());
                                pse.setInt(21, equip.getItemExp());
                                pse.setInt(22, equip.getRingId());
                                pse.setBoolean(23, equip.hasSkill());
                                pse.addBatch(); 
                            }
                        }
                        pse.executeBatch();
                    }
                }
            }
            System.out.print("Time to save " + (System.currentTimeMillis() - start));
        } catch (Exception e) {
            LogHelper.GENERAL_EXCEPTION.get().info("ItemFactory saveItems: " + e);
        } finally {
            lock.unlock();
        }
    }

附加内容:我对数据库还不熟悉。对数据库进行了一次介绍,我的其余经验仅仅来自于业余爱好项目和外部项目。也是一名大学生!

0 个答案:

没有答案