问题
I have something like the following code in my react native app to set up mock/test data for performance tests.
realm.write(() => {
const max = 120;
for(let x=1; x<=max; x++)
{
realm.create('Product', {productId:x});
}
for(let x=1; x<=max; x++)
{
for(let y=x; y<=max; y++)
{
for(let z=y; z<=max; z++)
{
realm.create('Compatibility', {
result: 'Y '+x+' '+y+' '+z,
products: [
realm.objects('Product').filtered('productId = '+x)[0],
realm.objects('Product').filtered('productId = '+y)[0],
realm.objects('Product').filtered('productId = '+z)[0]
]
});
}
}
}
});
class Product {}
Product.schema = {
name: 'Product',
primaryKey:'productId',
properties: {
productId:'int'
}
};
class Compatibility {}
Compatibility.schema = {
name: 'Compatibility',
properties: {
result: {type: 'string'},
products: {type: 'list',objectType:'Product'},
}
};
This means the Products object has 120 records and the Compatibility object has 1.7 million records.
When I run the query realm.objects('Compatibility').filtered(products.productId = 3 AND products.productId = 25 AND products.productId = 97), it takes about 15 seconds to run on my old HTC Desire 510 and my Huawei Nova Plus. This is too slow.
Is there a way to improve the speed of the query? For example, can you index the columns or something?
回答1:
First of all there is indexing in realm and primaryKeys are indexed already. So indexing in this scenario won't help you. But I think I have an idea of how you could get faster the process.
At the last for loop you are doing 3 queries. 2 of them happens unnecessarily I think since x and y values going to be same for 120 z values. If you implement something like the code below, it might help a little bit with the performance I think.
let productX;
let productY;
let productZ;
for (let x = 1; x <= max; x++)
{
productX = realm.objects('Product').filtered('productId = ' + x)[0];
for (let y = x; y <= max; y++)
{
productY = realm.objects('Product').filtered('productId = ' + y)[0];
for (let z = y; z <= max; z++)
{
productZ = realm.objects('Product').filtered('productId = ' + z)[0];
realm.create('Compatibility',
{
result: 'Y ' + x + ' ' + y + ' ' + z,
products: [ productX, productY, productZ]
});
}
}
}
A second though;
This might be a really bad idea and can be a terrible practice but I'm going to give as a thought practice.
If you are always doing query with 3 different productIds, you can create a string with all tree in a single property and query only that. This way you can use indexing.
Example
class Compatibility {}
Compatibility.schema = {
name: 'Compatibility',
properties: {
result: {type: 'string'},
productQueryHelper: { type: 'string', indexed: true }
products: {type: 'list',objectType:'Product'},
}
};
realm.create('Compatibility',
{
result: 'Y ' + x + ' ' + y + ' ' + z,
productQueryHelper: `${x}&${y}&${z}` // you can use any other separator that isn't possible to be in productId
products: [
realm.objects('Product').filtered('productId = ' + x)[0],
realm.objects('Product').filtered('productId = ' + y)[0],
realm.objects('Product').filtered('productId = ' + z)[0]
]
});
realm.objects('Compatibility').filtered('productQueryHelper = "3&25&97"')
回答2:
Try to set your primary keys as indexed.
Btw I've never had problems with performance using Realm. Nowadays I'm using Realm in a scenario to manage my notifications. I have a lot of queries running at some time and this never hurt the performance.
class Product {}
Product.schema = {
name: 'Product',
primaryKey:'productId',
properties: {
productId: { type: 'int', indexed: true }
}
};
class Compatibility {}
Compatibility.schema = {
name: 'Compatibility',
properties: {
result: {type: 'string'},
products: {type: 'list',objectType:'Product'},
}
};
来源:https://stackoverflow.com/questions/46394870/improve-the-speed-of-a-realm-query-in-react-native