2015-11-05 5 views
4

В таблице с строками> 100 тыс., Как я могу эффективно перетасовать значения определенного столбца?Столбец столбца PostgreSQL

определение Таблицы:

CREATE TABLE person 
(
    id integer NOT NULL, 
    first_name character varying, 
    last_name character varying, 
CONSTRAINT person_pkey PRIMARY KEY (id) 
) 

Для того, чтобы данные анонимным, я должен перетасовать значение столбца «first_name» вместо (я не позволило создать новую таблицу).

Моя попытка:

with 
first_names as (
select row_number() over (order by random()), 
     first_name as new_first_name 
from person 
), 
ids as (
select row_number() over (order by random()), 
     id as ref_id 
from person 
) 
update person 
set first_name = new_first_name 
from first_names, ids 
where id = ref_id; 

Это занимает несколько часов, чтобы закончить.

Есть ли эффективный способ сделать это?

+1

Ваши два, CTE не очень рандомизации данные , Вы просто генерируете случайные «номера строк», но затем вы их не используете. Если вы не будете использовать вызовы 'row_number()', это не будет отличаться. Вы также выполняете кросс-соединение между двумя CTE и таблицей 'person', что означает, что ваш оператор генерирует промежуточный результат из 100.000 * 100.000 * 100.000 строк. –

+0

http: // stackoverflow.com/a/3100232/3574819 может помочь сделать обновления быстрее – FuzzyTree

ответ

4

Проблема с Postgres является каждое обновление означает, delete + insert

  • Вы можете проверить анализ с использованием SELECT вместо UPDATE, чтобы увидеть, что производительность КТР
  • Вы можете отключить индекс, так обновление быстрее
  • Но самое лучшее решение, я использую, когда нужно обновить все строки, это создать таблицу снова

.

CREATE TABLE new_table AS 
    SELECT * .... 


DROP oldtable; 

Rename new_table to old_table 

CREATE index and constrains 

Извините, что разве вариант для вас :(

EDIT: После прочтения a_horse_with_no_name

выглядит как вам нужно

with 
first_names as (
    select row_number() over (order by random()) rn, 
      first_name as new_first_name 
    from person 
), 
ids as (
    select row_number() over (order by random()) rn, 
      id as ref_id 
    from person 
) 
update person 
set first_name = new_first_name 
from first_names 
join ids 
    on first_names.rn = ids.rn 
where id = ref_id; 

Опять на вопрос производительности лучше, если вам представить ANALYZE/EXPLAIN.

+0

Это правильная формулировка того, что планирует OP. Производительность, вероятно, такая же. –

+0

Это действительно удивительно быстро на моей тестовой таблице 500 000 строк: http://explain.depesz.com/s/Dwh –

+0

@a_horse_with_no_name Да на моем компьютере. OP-запрос. Я останавливаю его через 10 мин. Вы запрашиваете запуск за 150 секунд за 90 секунд. Так что мой взгляд на 40% быстрее. Теперь нужно выяснить, почему мой компьютер настолько медленный. Закончив мою пустыню и начнем проверять эту память. –

2

Это один занимает 5 секунд, чтобы перетасовать 500.000 строк на моем ноутбуке:

with names as (
    select id, first_name, last_name, 
     lead(first_name) over w as first_1, 
     lag(first_name) over w as first_2 
    from person 
    window w as (order by random()) 
) 
update person 
    set first_name = coalesce(first_1, first_2) 
from names 
where person.id = names.id; 

Идея заключается в том, чтобы выбрать «следующий» имя после сортировки данных в случайном порядке. Это так же хорошо, как выбор случайного имени.

Существует вероятность того, что не все имена перетасовываются, но если вы запустите его два или три раза, это должно быть достаточно хорошим.

Вот испытательная установка на SQLFiddle: http://sqlfiddle.com/#!15/15713/1

Запрос на правой стороне проверки если первое имя осталось то же самое после того, как «рандомизации»

+0

К сожалению, первый метод может выбирать одно и то же значение несколько раз и пропускать другие. Я не уверен, что это то, что намеревается OP. –

+0

Можете ли вы дать мне советы о том, как вы создаете таблицу образцов 500 000? –

+0

@GordonLinoff: Я пробовал это несколько раз с именами, которые содержали исходный идентификатор, и только один раз запускал, где одно имя не было изменено. Я думаю, что чем больше таблица, тем больше вероятность того, что это сработает. Тот, который имеет «случайное смещение», на самом деле не работает с небольшим количеством строк. –

Смежные вопросы