2013-12-17 2 views
0

В настоящее время я работаю над проектом с MySQL Db более 8 миллионов строк. Мне была предоставлена ​​часть его для проверки некоторых запросов. Он имеет около 20 столбцов, из которых 5 мне полезны. А именно: First_Name, Last_Name, Address_Line1, Address_Line2, Address_Line3, RefundIDОбновление с подзапросом никогда не завершено

Я должен создать уникальный, но случайный RefundID для каждой строки, это не проблема. Проблема заключается в создании таких жеRefundID для тех строк, у которых First_Name, Last_Name, Address_Line1, Address_Line2, Address_Line3 такой же.

Это моя первая работа, связанная с MySQL с таким большим количеством строк. До сих пор я создал эти запросы:

запрос
-- Creating Teporary Table -- 
CREATE temporary table tempT (SELECT tt.First_Name, count(tt.Address_Line1) as 
a1, count(tt.Address_Line2) as a2, count(tt.Address_Line3) as a3, tt.RefundID 
FROM `tempTable` tt GROUP BY First_Name HAVING a1 >= 2 AND a2 >= 2 AND a3 >= 2); 
-- Updating Rows with First_Name from tempT -- 
UPDATE `tempTable` SET RefundID = FLOOR(RAND()*POW(10,11)) 
WHERE First_Name IN (SELECT First_Name FROM tempT WHERE First_Name is not NULL); 

Это обновление не продолжает работать, но никогда не заканчивается, tempT имеет более 30K строк. Затем этот запрос будет запущен в основной БД с более чем 800 К строк.

Может ли кто-нибудь помочь мне с этим?

С уважением

ответ

1

решения, которые кажутся очевидными для меня ....

Не используйте случайное значение - использовать хэш:

UPDATE yourtable 
SET refundid = MD5('some static salt', First_Name 
    , Last_Name, Address_Line1, Address_Line2, Address_Line3) 

Проблема заключается в том что если вы используете целочисленное значение для refundId, тогда есть хорошие шансы получить столкновение (подсказка CONV (SUBSTR (MD5 (...), 1,16), 16,10), чтобы получить SIGNED BIGINT). Но вы не сказали, что такое тип поля, и как строгое «уникальное» требование было. Однако он выполняет обновление за один проход.

Альтернативный подход, который создает плотно упакованную последовательность чисел, заключается в создании временной таблицы с уникальными значениями из исходной таблицы и случайным значением. Сортировать по случайной величине и установите монотонно возрастающую refundId - использовать это в качестве справочной таблицы или обновить исходную таблицу:

SELECT DISTINCT First_Name 
    , Last_Name, Address_Line1, Address_Line2, Address_Line3 
INTO temptable 
FROM yourtable; 

set @counter=-1; 

UPDATE temptable t SET t,refundId=(@counter:[email protected] + 1) 
ORDER BY r.randomvalue; 

Есть и другие решения тоже - но более эффективных из них полагается на наличие нескольких копий данные и/или использование процедурного языка.

+0

Привет Спасибо за ваш ответ, RefundID должен быть уникальными значениями 9-12 цифр. MD5 имеет 32 цифры, я думаю (плохая числовая память). Я должен дать одинаковый идентификатор каждой строке, где 'First_Name, Last_Name, Address_Line1, Address_Line2, Address_Line3' одинаковы. С уважением –

+0

Да, я подозревал, что это может быть так и явным образом рассмотрел это в моем ответе выше. – symcbean

0

Попробуйте использовать следующее:

UPDATE `tempTable` x SET RefundID = FLOOR(RAND()*POW(10,11)) 
WHERE exists (SELECT 1 FROM tempT y WHERE First_Name is not NULL and x.First_Name=y.First_Name); 
+0

Я выполняю ваш запрос в данный момент, как долго вы думаете, что это займет i7 с 4GB Ram? Мои спецификации ПК. I.E для 30K строк. –

+0

Я бы не рискнул предположить, хотя, если бы это был я, я бы попробовал его с 100 результатами, затем 1000, затем 10000 и т. Д., Чтобы посмотреть, начнет ли он разрушаться. Также вы можете использовать объяснение, чтобы собрать то, что он делает это так долго. Однако версия существует быстрее. –

+0

Я пропустил его на 6 минут, и это никогда не заканчивалось, я попробую сначала с 10 рядами. Спасибо –

0

В MySQL, часто более эффективно использовать join с update, чем для фильтрации через п where с использованием подзапроса. Ниже будут работать лучше:

UPDATE `tempTable` join 
     (SELECT distinct First_Name 
     FROM tempT 
     WHERE First_Name is not NULL 
     ) fn 
     on temptable.First_Name = fn.First_Name 
    SET RefundID = FLOOR(RAND()*POW(10,11)); 
Смежные вопросы