Find ways to optimize these functions for performance:

class Database:
    def __init__(self):
        self.conn: Optional[aiosqlite.Connection] = None

    async def connect(self):
        try:
            self.conn = await aiosqlite.connect("main.db")
            await self.conn.execute("PRAGMA journal_mode=WAL;")
            self.conn.row_factory = aiosqlite.Row
        except aiosqlite.Error:
            logger.exception(
                "Exception occurred while connecting to main.db Database:\n"
            )
            pass

    async def get_all(self):
        users = await DB.execute(f"SELECT * FROM users", fetch="all")
        guilds = await DB.execute(f"SELECT * FROM guilds", fetch="all")
        data = {
            "users": [dict(i) for i in users],
            "guilds": [dict(i) for i in guilds],
        }

        return data

    @property
    def is_connected(self) -> bool:
        return self.conn is not None

    @staticmethod
    async def _fetch(cursor, mode) -> Optional[Any]:
        if mode == "one":
            return await cursor.fetchone()
        if mode == "many":
            return await cursor.fetchmany()
        if mode == "all":
            return await cursor.fetchall()

    async def execute(
        self, query: str, values: Tuple = (), *, fetch: str = None
    ) -> Optional[Any]:
        cursor = await self.conn.cursor()

        await cursor.execute(query, values)
        data = await self._fetch(cursor, fetch)
        await self.conn.commit()

        await cursor.close()
        return data

    async def execute_with_retry(
        self,
        query: str,
        values: Tuple = (),
        *,
        fetch: str = None,
        retries: int = 5,
        retry_delay: float = 1.0,
    ) -> Optional[Any]:
        for attempt in range(retries):
            try:
                return await self.execute(query, values, fetch=fetch)
            except OperationalError as e:
                if "locked" in str(e):
                    if attempt < retries - 1:
                        await asyncio.sleep(retry_delay)
                    else:
                        raise
                else:
                    raise


DB = Database()

async def create_user_favorite(user_id, favorite_ip, favorite_hostname):
    current_favorites = await get_favorites(user_id)
    if current_favorites and (
        len(current_favorites) == 25
        or favorite_ip in [d["ip"] for d in current_favorites]
    ):
        return False
    await DB.execute(
        f"INSERT INTO favorites(owner_id, ip, hostname, notifications) VALUES(?, ?, ?, ?)",
        (user_id, favorite_ip, favorite_hostname, json.dumps({})),
    )
    return True

async def update_user_favorite(user_id, favorite_ip, new_data):
    favorite = await DB.execute(
        f"SELECT * FROM favorites WHERE owner_id = ? AND ip = ?",
        (user_id, favorite_ip),
        fetch="one",
    )
    if favorite is None:
        logger.debug(
            f"Favorite [{user_id=}, {favorite_ip=}] was not found, therefore cannot be edited."
        )
        return

    favorite = dict(favorite)
    favorite["notifications"] = json.loads(favorite["notifications"])

    if "notifications" in new_data and not favorite["notifications"]:
        servers_with_notifs_num = len(
            [f for f in await get_favorites(user_id) if f["notifications"]]
        )
        if servers_with_notifs_num >= NOTIFICATION_LIMIT:
            return False

    items = []
    params = []
    for k, v in new_data.items():
        if not isinstance(v, str):
            logger.error(
                f"Item of type {type(v)} ('{v}') cannot be used to update the DB column."
            )
            continue
        items.append(f"SET {k} = ?")
        params.append(v)

    if len(items) == 0:
        logger.debug(
            f"Favorite [{user_id=}, {favorite_ip=}] was not updated, no valid data specified.\n{new_data=}"
        )
        return

    query = "UPDATE favorites " + ", ".join(items) + " WHERE owner_id = ? AND ip = ?"

    await DB.execute(query, (*params,) + (user_id, favorite_ip))
    return True

async def save_ms_servers(servers, cached_servers=None):
    # Use already loaded cache if provided
    if cached_servers is not None:
        cached_ips = set(s["ip"] for s in cached_servers)
    else:
        cached = await DB.execute("SELECT ip FROM ms_servers_cache", fetch="all")
        cached_ips = set(row["ip"] for row in cached)

    to_update = []
    to_insert = []

    for s in servers:
        status = json.dumps(s.status) if s.status is not None else "{}"
        info = json.dumps(s.info) if s.info is not None else "{}"
        players = json.dumps(s.players) if s.status is not None else "{}"
        if s.server_address in cached_ips:
            to_update.append((s.timestamp, status, info, players, s.server_address))
        else:
            to_insert.append((s.server_address, s.timestamp, status, info, players))

    # Batch UPDATE
    if to_update:
        await DB.conn.executemany(
            "UPDATE ms_servers_cache SET timestamp = ?, status = ?, info = ?, players = ? WHERE ip = ?",
            to_update,
        )
        await DB.conn.commit()

    # Batch INSERT
    if to_insert:
        await DB.conn.executemany(
            "INSERT INTO ms_servers_cache(ip, timestamp, status, info, players) VALUES(?, ?, ?, ?, ?)",
            to_insert,
        )
        await DB.conn.commit()

    # Return the updated cache
    return await load_ms_servers()

async def save_dict_to_db(table, data_dict, key_column):
    if not data_dict:
        return

    keys = list(data_dict.keys())
    placeholders = ", ".join(["?"] * len(keys))
    query = (
        f'SELECT "{key_column}" FROM {table} WHERE "{key_column}" IN ({placeholders})'
    )
    existing_rows = await DB.execute(query, tuple(keys), fetch="all")
    existing_keys = set(row[key_column] for row in existing_rows)

    to_update = []
    to_insert = []

    for key, data in data_dict.items():
        if not data:
            continue
        data[key_column] = key
        columns = list(data.keys())
        values = list(data.values())
        if key in existing_keys:
            update_placeholders = ", ".join(f'"{col}" = ?' for col in columns)
            to_update.append((values + [key], update_placeholders, columns))
        else:
            insert_placeholders = ", ".join("?" * len(values))
            cols = ", ".join(f'"{col}"' for col in columns)
            to_insert.append((cols, insert_placeholders, values))

    # Batch UPDATEs
    for values, update_placeholders, columns in to_update:
        await DB.execute_with_retry(
            f'UPDATE {table} SET {update_placeholders} WHERE "{key_column}" = ?',
            tuple(values),
        )

    # Batch INSERTs
    for cols, insert_placeholders, values in to_insert:
        await DB.execute_with_retry(
            f"INSERT INTO {table} ({cols}) VALUES ({insert_placeholders})",