LIKE语句中查询参数导致响应慢
Query parameters in LIKE Statement causes slow response
我正在尝试使用 node.js 客户端库使用查询参数查询 Google spanner。
但是,有查询参数的响应比没有查询参数的响应要慢得多。
查询有 LIKE(forward match) 语句。我找不到将查询参数与 LIKE 语句一起使用的推荐方法。
另外,我用equal语句测试过,带参数查询和不带参数查询没有区别。
Table 有超过 2000 万行。而实例是1个节点。
有什么解决办法吗?或者 Google 扳手有这个错误吗?
部分Schema(实际40多列):
CREATE TABLE props (
props__id STRING(MAX) NOT NULL,
props__address_quadkey STRING(MAX),
...
) PRIMARY KEY (props__id)
索引:
CREATE INDEX props__address_quadkey
ON props (
props__address_quadkey
)
测试代码:
const Spanner = require('@google-cloud/spanner');
const spanner = new Spanner();
const db = spanner
.instance('instance_name')
.database('database_name');
(async () => {
// Make connection
await db.run({ sql: 'SELECT 1' });
console.time('Without param');
const r1 = (await db.run({
sql: `
SELECT
props__id
FROM props@{FORCE_INDEX=props__address_quadkey}
WHERE
(props__address_quadkey LIKE '1330020303011010200%')
`
}))[0];
console.log(r1.length); // 121
console.timeEnd('Without param'); // Without param: 277.223ms
console.time('with param 1');
const r2 = (await db.run({
sql: `
SELECT
props__id
FROM props@{FORCE_INDEX=props__address_quadkey}
WHERE
(props__address_quadkey LIKE @quadkey)
`,
params: { quadkey: '1330020303011010200%' },
types: { quadkey: 'string' },
}))[0];
console.log(r2.length); // 121
console.timeEnd('with param 1'); // with param 1: 9240.822ms
})();
感谢您的帮助!
这是 Cloud Spanner 目前的一个限制。使用 LIKE
模式的常量值,Cloud Spanner 能够在查询编译期间基于 LIKE
模式优化查找表达式。例如,在这种情况下,Cloud Spanner 将能够生成一个查询计划,其查找表达式基本上是
STARTS_WITH(props__address_quadkey, 1330020303011010200)
这将能够有效地在索引中搜索与 LIKE
模式中的前缀匹配的条目。
但是对于参数化的 LIKE
模式,这是不可能的,因为参数直到执行时才被评估并且可以包含任何 LIKE
表达式。因此,Cloud Spanner 无法高效地查找匹配行,而是必须读取所有行并根据参数中的 LIKE
模式对其进行评估,以过滤掉不匹配的行。
然而,此限制不会影响更简单的谓词,例如 Cloud Spanner 能够根据参数值进行高效查找的相等谓词。
我正在尝试使用 node.js 客户端库使用查询参数查询 Google spanner。 但是,有查询参数的响应比没有查询参数的响应要慢得多。 查询有 LIKE(forward match) 语句。我找不到将查询参数与 LIKE 语句一起使用的推荐方法。
另外,我用equal语句测试过,带参数查询和不带参数查询没有区别。
Table 有超过 2000 万行。而实例是1个节点。
有什么解决办法吗?或者 Google 扳手有这个错误吗?
部分Schema(实际40多列):
CREATE TABLE props (
props__id STRING(MAX) NOT NULL,
props__address_quadkey STRING(MAX),
...
) PRIMARY KEY (props__id)
索引:
CREATE INDEX props__address_quadkey
ON props (
props__address_quadkey
)
测试代码:
const Spanner = require('@google-cloud/spanner');
const spanner = new Spanner();
const db = spanner
.instance('instance_name')
.database('database_name');
(async () => {
// Make connection
await db.run({ sql: 'SELECT 1' });
console.time('Without param');
const r1 = (await db.run({
sql: `
SELECT
props__id
FROM props@{FORCE_INDEX=props__address_quadkey}
WHERE
(props__address_quadkey LIKE '1330020303011010200%')
`
}))[0];
console.log(r1.length); // 121
console.timeEnd('Without param'); // Without param: 277.223ms
console.time('with param 1');
const r2 = (await db.run({
sql: `
SELECT
props__id
FROM props@{FORCE_INDEX=props__address_quadkey}
WHERE
(props__address_quadkey LIKE @quadkey)
`,
params: { quadkey: '1330020303011010200%' },
types: { quadkey: 'string' },
}))[0];
console.log(r2.length); // 121
console.timeEnd('with param 1'); // with param 1: 9240.822ms
})();
感谢您的帮助!
这是 Cloud Spanner 目前的一个限制。使用 LIKE
模式的常量值,Cloud Spanner 能够在查询编译期间基于 LIKE
模式优化查找表达式。例如,在这种情况下,Cloud Spanner 将能够生成一个查询计划,其查找表达式基本上是
STARTS_WITH(props__address_quadkey, 1330020303011010200)
这将能够有效地在索引中搜索与 LIKE
模式中的前缀匹配的条目。
但是对于参数化的 LIKE
模式,这是不可能的,因为参数直到执行时才被评估并且可以包含任何 LIKE
表达式。因此,Cloud Spanner 无法高效地查找匹配行,而是必须读取所有行并根据参数中的 LIKE
模式对其进行评估,以过滤掉不匹配的行。
然而,此限制不会影响更简单的谓词,例如 Cloud Spanner 能够根据参数值进行高效查找的相等谓词。