提升数据服务API性能:解析SQL时间占比优化与缓存机制的应用

这篇文章中,我们将探讨如何提升数据服务API的性能,特别关注于解析SQL时间占比的优化以及引入缓存机制来优化代码。在我们的分析中,我们发现解析SQL占据了大部分时间,因此我们将重点关注这个方面的优化。

1、问题分析

  数据服务api之前做过压测,从火焰图分析 解析SQL时间占比比较大,为了提高性能,我们需要专注于优化解析SQL的部分。

 
验签 获取apiinfo 解析SQL 执行动态SQL
11.18% 2.55% 28.03% 6.35%

2、优化前代码分析

本文提供优化前的代码示例,其中包括了解析MyBatis SQL的方法。该方法涉及使用XPathParser来解析SQL,创建SqlSource,并最终得到带有参数值的完整SQL。然后,该SQL用于获取分页数据。


/**
* mybatis sql解析
*
* @param databaseType 数据源类型 mysql,oracle,clickhouse
* @param sql mybatis模板sql
* @param params 参数
* @param pageDTO 分页参数
* @return
*/
private static String parseMybatisSql(String databaseType,
                                          String sql,
                                          Map<String, Object> params,
                                          ApiPageDTO pageDTO) {
        XPathParser xPathParser = new XPathParser(sql);
        XNode node = xPathParser.evalNode("select|insert|update|delete");
        Configuration configuration = new Configuration();
        LanguageDriver langDriver = configuration.getLanguageDriver(null);
        SqlSource sqlSource = langDriver.createSqlSource(configuration, node, null);
        BoundSql boundSql = sqlSource.getBoundSql(params);

        String sqlWithVal = getFullSql(configuration, boundSql);

        return DataBaseTypeEnum.getDataBaseTypeEnumByName(databaseType).getPageExpression(pageDTO, sqlWithVal);
    }

  • 每次API请求,SQL语句作为参数,然后从缓存中获取对应的SqlSource对象
  • 单例模式获取Configuration实例

3、优化方案

     提出了一种优化方案,以减少解析SQL的性能开销。新的代码示例使用了SqlSourceCache和ConfigurationSingleton两个关键组件。下面,我们对这两个组件进行详细说明。

SqlSourceCache

      SqlSourceCache 是一个缓存机制,它用于存储已解析的SQL语句。这有助于避免重复解析相同的SQL,从而提高性能。Cache最大容量设置为100,采用LRU策略,确保缓存不会无限增长。每当需要解析SQL时,该组件会检查缓存中是否已存在解析过的SQL,如果存在,则直接返回,否则执行解析并将其缓存。

ConfigurationSingleton

      ConfigurationSingleton 是一个单例模式的类,用于获取MyBatis的Configuration实例。这确保了只有一个Configuration实例存在,减少了不必要的资源开销。

优化后代码为

private static String parseMybatisSql(String databaseType,
                                          String sql,
                                          Map<String, Object> params,
                                          ApiPageDTO pageDTO) {
        SqlSource sqlSource = SqlSourceCache.getSqlSource(sql);
        BoundSql boundSql = sqlSource.getBoundSql(params);
        String sqlWithVal = getFullSql(ConfigurationSingleton.getInstance(), boundSql);

        return DataBaseTypeEnum.getDataBaseTypeEnumByName(databaseType).getPageExpression(pageDTO, sqlWithVal);
    }
public class SqlSourceCache {
private static final int CACHE_MAX = 100; private static final Map<String, SqlSource> cache = new LinkedHashMap<String, SqlSource>(CACHE_MAX, 0.75f, true) { // 重写removeEldestEntry方法来控制缓存的大小,使用LRU策略 @Override protected boolean removeEldestEntry(Map.Entry<String, SqlSource> eldest) { return size() > CACHE_MAX; } }; private SqlSourceCache() { // 私有构造函数,防止其他类实例化该类 } public static SqlSource getSqlSource(String encryptedSQL) { return cache.computeIfAbsent(encryptedSQL, SqlSourceCache::initSqlSource); } private static SqlSource initSqlSource(String encryptedSQL) { String sql = AesUtil.decryptAes(encryptedSQL, BaseConstant.SQL_ENCODE32_KEY); XPathParser xPathParser = new XPathParser(sql); XNode node = xPathParser.evalNode("select|insert|update|delete"); Configuration configuration = ConfigurationSingleton.getInstance(); LanguageDriver langDriver = configuration.getLanguageDriver(null); SqlSource sqlSource = langDriver.createSqlSource(configuration, node, null); return sqlSource; } }

 

public class ConfigurationSingleton {

    private static volatile Configuration instance;

    public static Configuration getInstance() {
        if (instance == null) {
            synchronized (ConfigurationSingleton.class) {
                if (instance == null) {
                    instance = new Configuration();
                }
            }
        }
        return instance;
    }

}

 4、优化效果

      这些优化措施的主要目的是减少解析SQL的时间,从而提高数据服务API的性能。通过将已解析的SQL缓存起来,我们避免了重复解析的开销,而通过单例模式的Configuration,我们减少了对象创建的开销。这两个优化措施相结合,可以显著提高数据服务API的性能,减少解析SQL所占用的时间,从而加速API的响应时间。

      这些优化措施对于处理大量API请求尤其重要,可以显著减少解析SQL的开销,提高API的响应速度。通过实施这些优化,可以提高数据服务API的性能,提供更快的响应时间。

posted @ 2023-10-16 15:30  LUDAGOGO  阅读(59)  评论(0)    收藏  举报