Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL优化-字符串中的字数-Postgresql_Sql_Postgresql_Optimization_Parallel Processing - Fatal编程技术网

SQL优化-字符串中的字数-Postgresql

SQL优化-字符串中的字数-Postgresql,sql,postgresql,optimization,parallel-processing,Sql,Postgresql,Optimization,Parallel Processing,我正试图用Postgresql上一个字段中的字数更新一个大约一百万行的大表。 此查询起作用,并设置token_count字段,对my_table中longtext中的tokens单词进行计数: myid是表的主键。 \\w+是必需的,因为我想计算单词数,忽略特殊字符。 例如,一次测试;将使用基于空间的计数返回5,而2是正确的值。 问题是速度非常慢,2天不足以在100万行上完成。 您将如何优化它?有没有办法避免加入 如何使用例如“限制”和“偏移”将批次拆分为块 谢谢你的提示 穆隆 更新:我测量了阵

我正试图用Postgresql上一个字段中的字数更新一个大约一百万行的大表。 此查询起作用,并设置token_count字段,对my_table中longtext中的tokens单词进行计数:

myid是表的主键。 \\w+是必需的,因为我想计算单词数,忽略特殊字符。 例如,一次测试;将使用基于空间的计数返回5,而2是正确的值。 问题是速度非常慢,2天不足以在100万行上完成。 您将如何优化它?有没有办法避免加入

如何使用例如“限制”和“偏移”将批次拆分为块

谢谢你的提示

穆隆

更新:我测量了阵列分割的性能,无论如何更新都会很慢。因此,也许一个解决方案将包括将其并行化。如果我从psql运行不同的查询,则只有一个查询可以工作,其他查询等待它完成。如何并行更新

确保myid已编制索引,作为索引中的第一个字段

首先考虑在DB外部执行此操作。很难说没有基准测试,但计数可能比选择+更新成本更高;所以这可能是值得的

使用COPY命令BCP equivalent for Postgres将表数据高效地批量复制到文件中

运行一个简单的Perl脚本进行计数。对于Perl来说,100万行应该需要几分钟到1小时,这取决于IO的速度

使用COPY将表复制回DB,可能是复制到临时表中,然后从该临时表更新;或者最好是截断主表并直接复制到其中(如果您能够承受停机时间的话)

对于您的方法和我的方法2的最后一步,以5000行为一批更新token_计数,例如,将rowcount设置为5000,并在token_计数为NULL时将更新循环到查询中

你试过使用数组长度吗

或者您的原始查询没有关联

UPDATE my_table
SET token_count = (
    select count(*)
    from (select unnest(regexp_matches(longtext, E'\\w+','g'))) s
    );
使用 获取tsvector列的统计信息

没有样本数据来尝试它,但它应该可以工作

样本数据
也许字符串到数组会更好?例如,选择array_lengthstring_至array'abc','',1选择array_lengthregexp_匹配'this is a test',E'\\w+','g',1;返回一个表,而不是单个计数:-/string_to_数组的一个问题是只考虑空格,而我的解决方案计算实际单词,而不是特殊字符。建议的解决方案将所有内容设置为1。添加一个计数,如前所述如何将查询限制为N行?将Perl作为内置语言之一的想法是将记录传入/传出数据库。为什么不在数据库内部使用Perl或任何其他内置语言?顺便说一句,在数据库外部使用表来更新其中一个字段的想法非常糟糕。@IgorRomanchenko-这取决于他们的设置。我已经习惯了中央数据库为100个应用程序和1000个用户提供服务——将这样的任务卸载到与数据库分离的服务器通常是个好主意。请注意,这将完全忽略停止字。
UPDATE my_table mt
SET token_count = array_length(regexp_split_to_array(trim(longtext), E'\\W+','g'), 1)
# select array_length(regexp_split_to_array(trim(' some long text  '), E'\\W+'), 1);
 array_length 
--------------
            3
(1 row)
UPDATE my_table
SET token_count = array_length(regexp_split_to_array(longtext, E'\\s+'), 1)
UPDATE my_table
SET token_count = (
    select count(*)
    from (select unnest(regexp_matches(longtext, E'\\w+','g'))) s
    );
SELECT *
FROM ts_stat($$
  SELECT to_tsvector(t.longtext)
  FROM my_table AS t
$$);
CREATE TEMP TABLE my_table
AS 
  SELECT $$A paragraph (from the Ancient Greek παράγραφος paragraphos, "to write beside" or "written beside") is a self-contained unit of a discourse in writing dealing with a particular point or idea. A paragraph consists of one or more sentences.$$::text AS longtext;

SELECT *
FROM ts_stat($$
  SELECT to_tsvector(t.longtext)
  FROM my_table AS t
$$);

     word     | ndoc | nentry 
--------------+------+--------
 παράγραφος   |    1 |      1
 written      |    1 |      1
 write        |    1 |      2
 unit         |    1 |      1
 sentenc      |    1 |      1
 self-contain |    1 |      1
 self         |    1 |      1
 point        |    1 |      1
 particular   |    1 |      1
 paragrapho   |    1 |      1
 paragraph    |    1 |      2
 one          |    1 |      1
 idea         |    1 |      1
 greek        |    1 |      1
 discours     |    1 |      1
 deal         |    1 |      1
 contain      |    1 |      1
 consist      |    1 |      1
 besid        |    1 |      2
 ancient      |    1 |      1
(20 rows)