[关闭]
@liyuj 2017-12-18T00:41:44.000000Z 字数 10526 阅读 5116

Apache-Ignite-2.3.0-中文开发手册

1.介绍

1.1.摘要

Apache Ignite是一个兼容ANSI-99、水平可扩展以及容错的分布式SQL数据库,这个分布式是以数据在集群范围的复制或者分区的形式提供的,具体的形式取决于使用场景。
作为一个SQL数据库,Ignite支持所有的DML指令,包括SELECT、UPDATE、INSERT和DELETE,它还实现了一个与分布式系统有关的DDL指令的子集。
Ignite的一个突出特性是完全支持分布式的SQL关联,Ignite支持并置和非并置的数据关联。并置时,关联是在每个节点的可用数据集上执行的,而不需要在网络上移动大量的数据,这种方式在分布式数据库中提供了最好的扩展性和性能。

和很多的分布式SQL数据库不同,对于数据和索引,Ignite将内存和磁盘都视为完整有效的存储层,但是磁盘是可选的,如果禁用的话,Ignite就变为纯内存数据库。
可以像其他的SQL存储一样,根据需要与Ignite进行交互,比如通过外部的工具或者应用使用JDBC或者ODBC驱动进行连接。在这之上,Java、.NET和C++开发者也可以使用Ignite的原生SQL API。

1.2.入门

1.2.1.摘要

Ignite支持数据定义语言(DDL)语句,可以在运行时创建和删除表和索引,还可以支持数据操作语言(DML)来执行查询,这些不管是Ignite的原生SQL API还是ODBC和JDBC驱动,都是支持的。
在下面的示例中,会使用一个包含两个表的模式,这些表会用于保存城市以及居住在那里的人的信息,假定一个城市有很多的人,并且人只会居住于一个城市,这是一个一对多(1:m)的关系。

1.2.2.连接

作为入门来说,可以使用一个SQL工具,在后面的SQL工具章节中会有一个示例来演示如何配置SQL工具。还可以使用SQLLine接入集群然后在命令行执行SQL语句。
如果希望从源代码入手,下面的示例代码会演示如果通过JDBC以及ODBC驱动来获得一个连接:
JDBC:

  1. // Register JDBC driver
  2. Class.forName("org.apache.ignite.IgniteJdbcThinDriver");
  3. // Open JDBC connection
  4. Connection conn = DriverManager.getConnection(
  5. "jdbc:ignite:thin://127.0.0.1/");

ODBC:

  1. // Combining connect string
  2. std::string connectStr = "DRIVER={Apache Ignite};SERVER=localhost;PORT=10800;SCHEMA=PUBLIC;";
  3. SQLCHAR outstr[ODBC_BUFFER_SIZE];
  4. SQLSMALLINT outstrlen;
  5. // Connecting to ODBC server
  6. SQLRETURN ret = SQLDriverConnect(dbc, NULL, reinterpret_cast<SQLCHAR*>(&connectStr[0]), static_cast<SQLSMALLINT>(connectStr.size()),
  7. outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE);

JDBC连接会使用thin模式驱动然后接入本地主机(127.0.0.1),一定要确保ignite-core.jar位于应用或者工具的类路径中,具体信息可以查看JDBC驱动相关的章节。
ODBC连接也是接入本地localhost,端口是10800,具体可以查看ODBC驱动相关的文档。
不管选择哪种方式,都需要打开一个命令行工具,然后转到{apache-ignite-version}/bin,然后执行ignite.sh或者ignite.bat脚本,这样可以启动一个或者多个节点,如果使用了Ignite.NET或者Ignite.C++,那么也可以使用对应的可执行文件启动一个节点。
Unix:

  1. ./ignite.sh

Windows:

  1. ignite.bat

.NET:

  1. platforms\dotnet\bin\Apache.Ignite.exe

C++ Windows

  1. modules\platforms\cpp\project\vs\x64\Release\ignite.exe

C++ Unix:

  1. ./modules/platforms/cpp/ignite/ignite

如果节点是通过Java应用启动,要保证在Maven的pom.xml文件中包含ignite-indexing模块依赖:

  1. <dependency>
  2. <groupId>org.apache.ignite</groupId>
  3. <artifactId>ignite-indexing</artifactId>
  4. <version>${ignite.version}</version>
  5. </dependency>

1.2.3.创建表

当前,创建的每个表都会位于PUBLIC模式,在模式和索引章节会有更详细的信息。
下面的示例代码会创建City和Person表:
SQL:

  1. CREATE TABLE City (
  2. id LONG PRIMARY KEY, name VARCHAR)
  3. WITH "template=replicated";
  4. CREATE TABLE Person (
  5. id LONG, name VARCHAR, city_id LONG, PRIMARY KEY (id, city_id))
  6. WITH "backups=1, affinityKey=city_id";

JDBC:

  1. // Create database tables
  2. try (Statement stmt = conn.createStatement()) {
  3. // Create table based on REPLICATED template
  4. stmt.executeUpdate("CREATE TABLE City (" +
  5. " id LONG PRIMARY KEY, name VARCHAR) " +
  6. " WITH \"template=replicated\"");
  7. // Create table based on PARTITIONED template with one backup
  8. stmt.executeUpdate("CREATE TABLE Person (" +
  9. " id LONG, name VARCHAR, city_id LONG, " +
  10. " PRIMARY KEY (id, city_id)) " +
  11. " WITH \"backups=1, affinityKey=city_id\"");
  12. }

ODBC:

  1. SQLHSTMT stmt;
  2. // Allocate a statement handle
  3. SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
  4. // Create table based on REPLICATED template
  5. SQLCHAR query1[] = "CREATE TABLE City ("
  6. "id LONG PRIMARY KEY, name VARCHAR) "
  7. "WITH \"template=replicated\"";
  8. SQLSMALLINT queryLen1 = static_cast<SQLSMALLINT>(sizeof(query1));
  9. SQLExecDirect(stmt, query, queryLen);
  10. // Create table based on PARTITIONED template with one backup
  11. SQLCHAR query2[] = "CREATE TABLE Person ( "
  12. "id LONG, name VARCHAR, city_id LONG "
  13. "PRIMARY KEY (id, city_id)) "
  14. "WITH \"backups=1, affinityKey=city_id\"";
  15. SQLSMALLINT queryLen2 = static_cast<SQLSMALLINT>(sizeof(query2));
  16. SQLExecDirect(stmt, query, queryLen);

CREATE TABLE命令执行之后,会做如下的工作:

和分布式缓存相关的参数是通过WITH子句传递的,如果忽略了WITH子句,那么缓存会使用CacheConfiguration对象的默认参数来创建。
在上面的示例中,对于Person表,Ignite创建了一个有一份备份数据的分布式缓存,city_id作为关系键,这些扩展参数是Ignite特有的,通过WITH进行传递,要为表配置其他的缓存参数,需要使用template参数,并且使用之前注册的缓存配置的名字(通过代码或者XML),具体可以参照扩展参数相关章节。
很多时候将不同的缓存键并置在一起非常有用,通常,业务逻辑需要访问不止一个缓存键,将他们并置在一起会确保具有相同affinityKey的所有键会被缓存在同一个节点上,这样就不需要从远程获取数据以避免耗时的网络开销。
在本示例中,有CityPerson对象,并且希望并置Person对象及其居住的City对象,要做到这一点,就像上例所示,使用了WITH子句并且指定了affinityKey=city_id

1.2.4.创建索引

定义索引可以加快查询的速度,下面是创建索引的示例:
SQL:

  1. CREATE INDEX idx_city_name ON City (name)
  2. CREATE INDEX idx_person_name ON Person (name)

JDBC:

  1. // Create indexes
  2. try (Statement stmt = conn.createStatement()) {
  3. // Create an index on the City table
  4. stmt.executeUpdate("CREATE INDEX idx_city_name ON City (name)");
  5. // Create an index on the Person table
  6. stmt.executeUpdate("CREATE INDEX idx_person_name ON Person (name)");
  7. }

ODBC:

  1. SQLHSTMT stmt;
  2. // Allocate a statement handle
  3. SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
  4. // Create an index on the City table
  5. SQLCHAR query[] = "CREATE INDEX idx_city_name ON City (name)";
  6. SQLSMALLINT queryLen = static_cast<SQLSMALLINT>(sizeof(query));
  7. SQLRETURN ret = SQLExecDirect(stmt, query, queryLen);
  8. // Create an index on the Person table
  9. SQLCHAR query2[] = "CREATE INDEX idx_person_name ON Person (name)";
  10. SQLSMALLINT queryLen2 = static_cast<SQLSMALLINT>(sizeof(query2));
  11. ret = SQLExecDirect(stmt, query2, queryLen2);

1.2.5.插入数据

对数据进行查询之前,需要在两个表中加载部分数据,下面是如何往表中插入数据的示例:
SQL:

  1. INSERT INTO City (id, name) VALUES (1, 'Forest Hill');
  2. INSERT INTO City (id, name) VALUES (2, 'Denver');
  3. INSERT INTO City (id, name) VALUES (3, 'St. Petersburg');
  4. INSERT INTO Person (id, name, city_id) VALUES (1, 'John Doe', 3);
  5. INSERT INTO Person (id, name, city_id) VALUES (2, 'Jane Roe', 2);
  6. INSERT INTO Person (id, name, city_id) VALUES (3, 'Mary Major', 1);
  7. INSERT INTO Person (id, name, city_id) VALUES (4, 'Richard Miles', 2);

JDBC:
// Populate City table
try (PreparedStatement stmt =
conn.prepareStatement("INSERT INTO City (id, name) VALUES (?, ?)")) {

stmt.setLong(1, 1L);
stmt.setString(2, "Forest Hill");
stmt.executeUpdate();

stmt.setLong(1, 2L);
stmt.setString(2, "Denver");
stmt.executeUpdate();

stmt.setLong(1, 3L);
stmt.setString(2, "St. Petersburg");
stmt.executeUpdate();

}

// Populate Person table
try (PreparedStatement stmt =
conn.prepareStatement("INSERT INTO Person (id, name, city_id) VALUES (?, ?, ?)")) {

stmt.setLong(1, 1L);
stmt.setString(2, "John Doe");
stmt.setLong(3, 3L);
stmt.executeUpdate();

stmt.setLong(1, 2L);
stmt.setString(2, "Jane Roe");
stmt.setLong(3, 2L);
stmt.executeUpdate();

stmt.setLong(1, 3L);
stmt.setString(2, "Mary Major");
stmt.setLong(3, 1L);
stmt.executeUpdate();

stmt.setLong(1, 4L);
stmt.setString(2, "Richard Miles");
stmt.setLong(3, 2L);
stmt.executeUpdate();

}
ODBC:

  1. SQLHSTMT stmt;
  2. // Allocate a statement handle
  3. SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
  4. // Populate City table
  5. SQLCHAR query1[] = "INSERT INTO City (id, name) VALUES (?, ?)";
  6. SQLRETURN ret = SQLPrepare(stmt, query1, static_cast<SQLSMALLINT>(sizeof(query1)));
  7. char name[1024];
  8. int32_t key = 1;
  9. strncpy(name, "Forest Hill", sizeof(name));
  10. ret = SQLExecute(stmt);
  11. key = 2;
  12. strncpy(name, "Denver", sizeof(name));
  13. ret = SQLExecute(stmt);
  14. key = 3;
  15. strncpy(name, "Denver", sizeof(name));
  16. ret = SQLExecute(stmt);
  17. // Populate Person table
  18. SQLCHAR query2[] = "INSERT INTO Person (id, name, city_id) VALUES (?, ?, ?)";
  19. ret = SQLPrepare(stmt, query2, static_cast<SQLSMALLINT>(sizeof(query2)));
  20. key = 1;
  21. strncpy(name, "John Doe", sizeof(name));
  22. int32_t city_id = 3;
  23. ret = SQLExecute(stmt);
  24. key = 2;
  25. strncpy(name, "Jane Roe", sizeof(name));
  26. city_id = 2;
  27. ret = SQLExecute(stmt);
  28. key = 3;
  29. strncpy(name, "Mary Major", sizeof(name));
  30. city_id = 1;
  31. ret = SQLExecute(stmt);
  32. key = 4;
  33. strncpy(name, "Richard Miles", sizeof(name));
  34. city_id = 2;
  35. ret = SQLExecute(stmt);

Java API

  1. // Connecting to the cluster.
  2. Ignite ignite = Ignition.start();
  3. // Getting a reference to an underlying cache created for City table above.
  4. IgniteCache<Long, City> cityCache = ignite.cache("SQL_PUBLIC_CITY");
  5. // Getting a reference to an underlying cache created for Person table above.
  6. IgniteCache<PersonKey, Person> personCache = ignite.cache("SQL_PUBLIC_PERSON");
  7. // Inserting entries into City.
  8. SqlFieldsQuery query = new SqlFieldsQuery(
  9. "INSERT INTO City (id, name) VALUES (?, ?)");
  10. cityCache.query(query.setArgs(1, "Forest Hill")).getAll();
  11. cityCache.query(query.setArgs(2, "Denver")).getAll();
  12. cityCache.query(query.setArgs(3, "St. Petersburg")).getAll();
  13. // Inserting entries into Person.
  14. query = new SqlFieldsQuery(
  15. "INSERT INTO Person (id, name, city_id) VALUES (?, ?, ?)");
  16. personCache.query(query.setArgs(1, "John Doe", 3)).getAll();
  17. personCache.query(query.setArgs(2, "Jane Roe", 2)).getAll();
  18. personCache.query(query.setArgs(3, "Mary Major", 1)).getAll();
  19. personCache.query(query.setArgs(4, "Richard Miles", 2)).getAll();

1.2.6.查询数据

数据加载之后,就可以执行查询了。下面就是如何查询数据的示例,其中包括两个表之间的关联:
SQL:

  1. SELECT *
  2. FROM City;
  3. SELECT name
  4. FROM City
  5. WHERE id = 1;
  6. SELECT p.name, c.name
  7. FROM Person p, City c
  8. WHERE p.city_id = c.id;

JDBC:

  1. // Get data using an SQL join sample.
  2. try (Statement stmt = conn.createStatement()) {
  3. try (ResultSet rs =
  4. stmt.executeQuery("SELECT p.name, c.name " +
  5. " FROM Person p, City c " +
  6. " WHERE p.city_id = c.id")) {
  7. System.out.println("Query result:");
  8. while (rs.next())
  9. System.out.println(">>> " + rs.getString(1) +
  10. ", " + rs.getString(2));
  11. }
  12. }

ODBC:

  1. SQLHSTMT stmt;
  2. // Allocate a statement handle
  3. SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
  4. // Get data using an SQL join sample.
  5. SQLCHAR query[] = "SELECT p.name, c.name "
  6. "FROM Person p, City c "
  7. "WHERE p.city_id = c.id";
  8. SQLSMALLINT queryLen = static_cast<SQLSMALLINT>(sizeof(query));
  9. SQLRETURN ret = SQLExecDirect(stmt, query, queryLen);

Java API

  1. // Connecting to the cluster.
  2. Ignite ignite = Ignition.start();
  3. // Getting a reference to an underlying cache created for City table above.
  4. IgniteCache<Long, City> cityCache = ignite.cache("SQL_PUBLIC_CITY");
  5. // Querying data from the cluster using a distributed JOIN.
  6. SqlFieldsQuery query = new SqlFieldsQuery("SELECT p.name, c.name " +
  7. " FROM Person p, City c WHERE p.city_id = c.id");
  8. FieldsQueryCursor<List<?>> cursor = cityCache.query(query);
  9. Iterator<List<?>> iterator = cursor.iterator();
  10. System.out.println("Query result:");
  11. while (iterator.hasNext()) {
  12. List<?> row = iterator.next();
  13. System.out.println(">>> " + row.get(0) + ", " + row.get(1));
  14. }

1.2.7.修改数据

有时数据是需要修改的,这时就可以执行修改操作来修改已有的数据,下面是如何修改数据的示例:
SQL:

  1. UPDATE City
  2. SET name = 'Foster City'
  3. WHERE id = 2;

JDBC:

  1. // Update
  2. try (Statement stmt = conn.createStatement()) {
  3. // Update City
  4. stmt.executeUpdate("UPDATE City SET name = 'Foster City' WHERE id = 2");
  5. }

ODBC:

  1. SQLHSTMT stmt;
  2. // Allocate a statement handle
  3. SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
  4. // Update City
  5. SQLCHAR query[] = "UPDATE City SET name = 'Foster City' WHERE id = 2"
  6. SQLSMALLINT queryLen = static_cast<SQLSMALLINT>(sizeof(query));
  7. SQLRETURN ret = SQLExecDirect(stmt, query, queryLen);

Java API

  1. // Updating a city entry.
  2. SqlFieldsQuery query = new SqlFieldsQuery(
  3. "UPDATE City SET name = 'Foster City' WHERE id = 2");
  4. cityCache.query(query).getAll();

1.2.8.删除数据

可能还需要从数据库中删除数据,下面是删除数据的示例:
SQL:

  1. DELETE FROM Person
  2. WHERE name = 'John Doe'

JDBC:

  1. // Delete
  2. try (Statement stmt = conn.createStatement()) {
  3. // Delete from Person
  4. stmt.executeUpdate("DELETE FROM Person WHERE name = 'John Doe'");
  5. }

ODBC:

  1. SQLHSTMT stmt;
  2. // Allocate a statement handle
  3. SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
  4. // Delete from Person
  5. SQLCHAR query[] = "DELETE FROM Person WHERE name = 'John Doe'"
  6. SQLSMALLINT queryLen = static_cast<SQLSMALLINT>(sizeof(query));
  7. SQLRETURN ret = SQLExecDirect(stmt, query, queryLen);

Java API

  1. // Removing a person.
  2. SqlFieldsQuery query = new SqlFieldsQuery(
  3. "DELETE FROM Person WHERE name = 'John Doe'");
  4. personCache.query(query).getAll();

1.2.9.示例

GitHub上有和这个入门文档有关的完整代码

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注