Apache Ignite与SQL Server性能

问题描述 投票:0回答:3

我们正在考虑使用内存数据库(例如Apache Ignite)来处理性能密集的类BI操作。因此,作为一个(非常原始的)示例,我从一个csv文件(14列)中填充了250.000条记录的Apache Ignite并进行了一些分组操作。以前,我还使用相同的数据对MS SQL-Server进行一些性能测试。

有趣和意外的是,MS SQL-Server需要大约0.25秒来执行此操作,而使用Apache Ignite则需要1-2秒。

1,我总是认为Apache Ignite不仅是分布式计算的一个很好的选择,而且由于其面向内存的架构,与传统的关系数据库相比也带来了性能提升。真的吗?为什么我的例子慢?

2,我是否以错误的方式使用Apache Ignite,还是有一些我应该使用的其他调优选项?

这是我在我的例子中使用的源代码:

  private static Connection conn = null;
  private static Statement stmt = null;
  private static ResultSet rs = null;

  private static void initialize() throws ClassNotFoundException, SQLException

  {

       // Register JDBC driver.
    Class.forName("org.apache.ignite.IgniteJdbcThinDriver");

    // Create database tables.
    stmt = conn.createStatement();

    // Create table
    stmt.executeUpdate("CREATE TABLE PIVOT_TEST (" +
    " REGION VARCHAR, COUNTRY VARCHAR, ITEM_TYPE VARCHAR, SALES_CHANNEL VARCHAR, ORDER_PRIORITY VARCHAR, ORDER_DATE VARCHAR, ORDER_ID VARCHAR PRIMARY KEY, "
    + "SHIP_DATE VARCHAR, UNITS_SOLD NUMERIC, UNIT_PRICE NUMERIC, UNIT_COST NUMERIC, TOTAL_REVENUE NUMERIC, TOTAL_COST NUMERIC, TOTAL_PROFIT NUMERIC )");

  }



  private static void fill() throws ClassNotFoundException, SQLException
  {
        // Register JDBC driver
        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");

        // Populate table
        PreparedStatement stmt =
        conn.prepareStatement("COPY FROM 'LINK_TO_CSV_FILE'" +

        "INTO PIVOT_TEST (REGION , COUNTRY , ITEM_TYPE , SALES_CHANNEL , ORDER_PRIORITY , ORDER_DATE , ORDER_ID , SHIP_DATE , UNITS_SOLD , UNIT_PRICE , UNIT_COST , TOTAL_REVENUE , TOTAL_COST , TOTAL_PROFIT ) FORMAT CSV");
        stmt.executeUpdate();

        stmt = conn.prepareStatement("CREATE INDEX index_name ON PIVOT_TEST(COUNTRY)");
        stmt.executeUpdate();
  }



  private static void getResult() throws ClassNotFoundException, SQLException
  {
        // Register JDBC driver
        Class.forName("org.apache.ignite.IgniteJdbcThinDriver");

        // Get data
        stmt = conn.createStatement();

        rs =
            stmt.executeQuery("SELECT AVG(UNIT_PRICE) AS AVG_UNIT_PRICE, MAX(UNITS_SOLD) AS MAX_UNITS_SOLD, SUM(UNIT_COST) AS SUM_UNIT_COST, AVG(TOTAL_REVENUE) AS AVG_TOTAL_REVENUE , AVG(TOTAL_COST) AS AVG_TOTAL_COST, AVG(TOTAL_PROFIT) as AVG_TOTAL_PROFIT  FROM PIVOT_TEST GROUP BY COUNTRY;");

        retrieveResultSet();      

  }



  private static void retrieveResultSet() throws SQLException
  {
        while (rs.next())
        {
                for(int i=0; i<rs.getMetaData().getColumnCount(); i++)
                {
                    rs.getObject(i+1);
                }
        }
  }



  public static void main(String[] args) throws SQLException, ClassNotFoundException

  {

        Ignite ignite = null;

        try

        {

            //--------------------------------CONNECTION-------------------//

            IgniteConfiguration configuration = new IgniteConfiguration();

            ignite = Ignition.start(configuration);

            conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1/");

            initialize();

            fill();


            long endPrepTable = System.currentTimeMillis();

            getResult();

            long endGetResult = System.currentTimeMillis();

            System.out.println("Get Result (s)" + " " + (endGetResult - endPrepTable)*1.0/1000);

        }

        catch(Exception e)
        {
            e.printStackTrace();
        }

        finally
        {
          ignite.close();

          conn.close();

          rs.close();
        }

  }

谢谢您的帮助!

ignite in-memory-database
3个回答
0
投票

您可以应用以下转折点:

  1. 使用并置标志[1]: JDBC:点燃:瘦://127.0.0.1;并列=真
  2. 为rs.getMetaData()。getColumnCount()引入一个变量: int count = rs.getMetaData()。getColumnCount(); while(rs.next()){for(int i = 0; i <count; i ++)rs.getObject(i + 1); }

[1] https://apacheignite-sql.readme.io/docs/jdbc-driver#section-parameters

[2] https://apacheignite.readme.io/docs/affinity-collocation#collocate-data-with-data


0
投票

与任何数据库一样,有许多方法可以调整和优化它。 Ignite的设计与SQL Server有着不同的权衡 - 不可能保证它在每种情况下都会更快。

话虽如此,有一些documentation on improving performance

需要考虑的事项:百万分之一的记录并不是那么多。 Ignite经过优化,可以在可以并行运行的集群中运行。使用单个“硬”查询,您可能需要增加queryParallelism,否则您将被限制为每个节点中的单个线程。

当然,你也可以做像EXPLAIN PLAN这样的事情,以确保它使用正确的索引等。与任何优化练习一样,它既是一门艺术,也是一门科学。


0
投票

将Ignite与关系数据库进行比较时,需要考虑以下几点:

  • Ignite SQL引擎针对多节点部署进行了优化,RAM作为主存储。不要尝试将单节点Ignite群集与针对此类配置进行了优化的关系数据库进行比较。使用RAM中的整个数据副本部署多节点群集。
  • 在数据建模和优化过程中考虑基本建议,如亲和力搭配,二级索引和其他listed here
  • 另外,请记住,关系数据库利用本地缓存技术并依赖于总数据大小,并且在多节点配置中,查询类型可以比Ignite更快地完成某些查询。例如,我看到一个SQL服务器在5毫秒内完成下面的查询,而8毫秒内的Ignite单节点集群和20毫秒内的4节点集群: SELECT * FROM输入i JOIN方pr ON(pr.prt_id)=(i.mbr_id)顺序i.input_id偏移0限制100 这是预期的,因为数据集大小约为64GB,SQL Server可以在本地RAM中缓存很多。此外,与单节点通信相比,节点内通信的成本影响了4个节点集群的数量。 要释放分布式内存计算的强大功能,请将更多数据预加载到集群或/并强制SQL Server通过检查更复杂的查询(如下所示)来转到磁盘: SELECT * FROM输入i INNER JOIN产品p ON(i.product_id)=(p.product_id)INNER JOIN Party pr ON(pr.prt_id)=(i.mbr_id)和(pr.session_id = i.session_id)我在哪里PRODUCT_ID = 5和I.SOURCE_ID = 6 就我而言,相同配置的SQL Server需要510秒,完成查询需要64GB数据(它必须转到磁盘)。 Ignite的4个节点集群在32秒内完成,8个节点集群在8秒内完成。
© www.soinside.com 2019 - 2024. All rights reserved.