Android房间@关系和索引
我在我的房间设置中有这个类,它将我的Android房间@关系和索引,android,android-room,Android,Android Room,我在我的房间设置中有这个类,它将我的状态表中的数据与我的国家表中的相应数据组合在一起: public class StateWithCountryData { @Embedded public State state; @Relation(parentColumn = "country_id", entityColumn = "_id", entity = Country.class) public Country country; } 正如您在my@Rel
状态
表中的数据与我的国家
表中的相应数据组合在一起:
public class StateWithCountryData {
@Embedded
public State state;
@Relation(parentColumn = "country_id", entityColumn = "_id", entity = Country.class)
public Country country;
}
正如您在my@Relationship代码中所看到的,mystates
country\u id
列与mycountries
列合并
我想知道的是@relationcode是否会在states
country\u id
上创建一个自动索引,还是我需要自己在State实体类中创建索引
如果是后者,我如何将所需的添加到我的状态实体类中?这是:
@Entity(tableName = "states")
public class State {
@PrimaryKey
@ColumnInfo(name = "_id")
private long stateId;
@NonNull
@ColumnInfo(name = "state_name")
private String stateName;
@ColumnInfo(name = "country_id")
private long countryId;
@ColumnInfo(name = "last_modified")
private Date lastModified;
public State(long stateId, @NonNull String stateName, long countryId, Date lastModified) {
this.stateId = stateId;
this.stateName = stateName;
this.countryId = countryId;
this.lastModified = lastModified;
}
public long getStateId() {
return stateId;
}
public void setStateId(long stateId) {
this.stateId = stateId;
}
@NonNull
public String getStateName() {
return stateName;
}
public void setStateName(@NonNull String stateName) {
this.stateName = stateName;
}
public long getCountryId() {
return countryId;
}
public void setCountryId(long countryId) {
this.countryId = countryId;
}
public Date getLastModified() {
return lastModified;
}
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
}
我想知道的是@relationcode是否会在states.country_id上创建一个自动索引,还是我需要自己在State实体类中创建索引
检查的方法是查看为@database生成的代码,例如,您会得到如下结果:-
final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate(1) {
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `Country` (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`))");
_db.execSQL("CREATE TABLE IF NOT EXISTS `states` (`_id` INTEGER NOT NULL, `state_name` TEXT NOT NULL, `country_id` INTEGER NOT NULL, `last_modified` TEXT, PRIMARY KEY(`_id`))");
_db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
_db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '008d8fa1f719c970d7a1182e9e43f80b')");
}
.....
如您所见,答案是否定的
如果是后者,我如何将所需的索引添加到我的状态实体类中
您可以使用:-
@Entity(tableName = "states"
, indices = {@Index(name = "ixCountryId", value = "country_id")} //<<<<<<<<<< ADDED
)
i、 e.线路
_db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `ixCountryId` ON `states` (`country_id`)");
已添加
一个更简单的选项是在@ColumnInfo级别编码,而不是在@Entity级别编码标记,例如
@ColumnInfo(name = "country_id", index = true)
private long countryId;
在上述情况下,这将自动生成索引名和结果,生成的代码中包含以下内容(而不是前面显示的行):-
您也可以同时使用这两种方法(不是您会做的事情,因为这是一种浪费/低效),这将导致:-
_db.execSQL("CREATE INDEX IF NOT EXISTS `ix01` ON `states` (`country_id`)");
_db.execSQL("CREATE INDEX IF NOT EXISTS `index_states_country_id` ON `states` (`country_id`)");
- @Entity级别的编码提供了更多选项,如复杂(多列)或唯一索引
SELECT * FROM states WHERE country_id > 500;
SELECT * FROM states JOIN Country ON Country.id = states.country_id WHERE country_id < 500;
从国家id>500的州中选择*;
选择*FROM states JOIN Country.id=states.Country\u id,其中Country\u id<500;
在创建索引之前和之后,索引之前的计时是
SELECT * FROM states WHERE country_id > 500
> OK
> Time: 0.563s
SELECT * FROM states JOIN Country ON Country.id = states.country_id WHERE country_id < 500
> OK
> Time: 0.074s
从国家/地区id>500的州中选择*
>嗯
>时间:0.563s
选择*FROM states JOIN Country.id=states.Country\u id,其中Country\u id<500
>嗯
>时间:0.074s
在创建索引之后,有:-
SELECT * FROM states WHERE country_id > 500
> OK
> Time: 2.764s
SELECT * FROM states JOIN Country ON Country.id = states.country_id WHERE country_id < 500
> OK
> Time: 0.158s
从国家/地区id>500的州中选择*
>嗯
>时间:2.764s
选择*FROM states JOIN Country.id=states.Country\u id,其中Country\u id<500
>嗯
>时间:0.158s
因此索引速度较慢(第一次查询大约慢5倍,第二次查询慢9.5倍)
在运行查询之前,代码还会执行解释查询计划 创建索引之前:- 问题1:- 问题2:- 创建索引后 问题1:- 问题2:- 使用的代码(使用Navicat):-
DROP TABLE IF EXISTS Country;
DROP TABLE IF EXISTS states;
CREATE TABLE IF NOT EXISTS `Country` (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`));
CREATE TABLE IF NOT EXISTS `states` (`_id` INTEGER NOT NULL, `state_name` TEXT NOT NULL, `country_id` INTEGER NOT NULL, `last_modified` TEXT, PRIMARY KEY(`_id`));
/* Load data into the Country table */
WITH RECURSIVE cte1(counter,base) AS (
SELECT 1, 'COUNTRY_A'
UNION ALL SELECT counter+1,'COUNTRY_A' FROM cte1 LIMIT 10000
)
INSERT INTO Country (name) SELECT base||counter FROM cte1;
/* Load fata into the states table */
WITH RECURSIVE cte1(counter,base,cid) AS (
SELECT 1,'STATE_S', (abs(random()) % (SELECT count() FROM Country)) + 1
UNION ALL SELECT
counter+1,
'STATE_S',
(abs(random()) % (SELECT count() FROM Country)) + 1
FROM cte1 LIMIT 500000
)
INSERT INTO states (state_name, country_id) SELECT base||counter, cid FROM cte1;
EXPLAIN QUERY PLAN
SELECT * FROM states JOIN Country ON Country.id = states.country_id WHERE country_id < 500;
EXPLAIN QUERY PLAN
SELECT * FROM states WHERE country_id > 500;
SELECT * FROM states WHERE country_id > 500;
SELECT * FROM states JOIN Country ON Country.id = states.country_id WHERE country_id < 500;
/* Create the Index */
CREATE INDEX IF NOT EXISTS `ix01` ON `states` (`country_id`);
EXPLAIN QUERY PLAN
SELECT * FROM states JOIN Country ON Country.id = states.country_id WHERE country_id < 500;
EXPLAIN QUERY PLAN
SELECT * FROM states WHERE country_id > 500;
SELECT * FROM states WHERE country_id > 500;
SELECT * FROM states JOIN Country ON Country.id = states.country_id WHERE country_id < 500;
/* Show states per country */
SELECT Country.name,count() AS states_inCountry FROM States JOIN Country ON country_id = Country.id GROUP BY country_id;
/* Clean up */
DROP INDEX IF EXISTS ix01;
DROP TABLE IF EXISTS states;
DROP TABLE If EXISTS Country;
删除表格(如果国家/地区存在);
如果存在状态,则删除表;
如果不存在“Country”(`id`整数不为NULL,`name`文本,主键(`id`)),则创建表;
如果不存在“states”(“state”id“INTEGER NOT NULL”,“state”name“TEXT NOT NULL”,“country”id“INTEGER NOT NULL”,“last_modified”TEXT,主键(“'u id')),则创建表;
/*将数据加载到国家/地区表中*/
递归cte1(计数器,基)为(
选择1,“国家/地区”
联合所有选择计数器+1,cte1限制10000中的“国家/地区”
)
插入国家/地区(名称),从cte1中选择基本| |计数器;
/*将fata加载到状态表中*/
递归cte1(计数器、基、cid)为(
选择1,'STATE_S',(abs(random())%(SELECT count()FROM Country))+1
联合所有选择
计数器+1,
“州”,
(abs(random())%(从国家/地区选择count())+1
从cte1限额500000起
)
插入州(州名称、国家id)选择基本计数器、cte1中的cid;
解释查询计划
选择*FROM states JOIN Country.id=states.Country\u id,其中Country\u id<500;
解释查询计划
从国家/地区id>500的州中选择*;
从国家/地区id>500的州中选择*;
选择*FROM states JOIN Country.id=states.Country\u id,其中Country\u id<500;
/*创建索引*/
如果“州”(“国家/地区id”)上不存在“ix01”,则创建索引;
解释查询计划
选择*FROM states JOIN Country.id=states.Country\u id,其中Country\u id<500;
解释查询计划
从国家/地区id>500的州中选择*;
从国家/地区id>500的州中选择*;
选择*FROM states JOIN Country.id=states.Country\u id,其中Country\u id<500;
/*显示每个国家的州*/
选择Country.name,count(),因为counters\u incontry从states加入Country\u id=Country.id按Country\u id分组;
/*清理*/
如果存在ix01,则删除索引;
如果存在状态,则删除表;
如果国家/地区存在,则删除表格;
- 注意,这可能有点不公平的比较/测试,因为索引创建可能会对后续运行条件产生影响。理想情况下,查询应该彼此分开运行,并且与索引创建分开
final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate(1) {
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `Country` (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`))");
_db.execSQL("CREATE TABLE IF NOT EXISTS `states` (`_id` INTEGER NOT NULL, `state_name` TEXT NOT NULL, `country_id` INTEGER NOT NULL, `last_modified` TEXT, PRIMARY KEY(`_id`))");
_db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
_db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '008d8fa1f719c970d7a1182e9e43f80b')");
}
.....
如您所见,答案是否定的
如果是后者,我如何将所需的索引添加到我的状态实体类中
您可以使用:-
@Entity(tableName = "states"
, indices = {@Index(name = "ixCountryId", value = "country_id")} //<<<<<<<<<< ADDED
)
i、 e.线路
_db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `ixCountryId` ON `states` (`country_id`)");
已添加
一个更简单的选择是使用c