Mysql: створити індекс на 1,4 мільярда записів


9

У мене є таблиця з 1,4 мільярдами записів. Структура таблиці така:

CREATE TABLE text_page (
    text VARCHAR(255),
    page_id INT UNSIGNED
) ENGINE=MYISAM DEFAULT CHARSET=ascii

Вимога - створити індекс над стовпцем text.

Розмір столу - близько 34G.

Я спробував створити індекс за допомогою наступного твердження:

ALTER TABLE text_page ADD KEY ix_text (text)

Після 10-годинного очікування я нарешті відмовився від такого підходу.

Чи є якесь дієве рішення цієї проблеми?

ОНОВЛЕННЯ : таблиця навряд чи буде оновлена, вставлена ​​або видалена. Причина створення індексу на стовпці textполягає в тому, що такий запит sql часто виконується:

SELECT page_id FROM text_page WHERE text = ?

ОНОВЛЕННЯ : Я вирішив проблему, розділивши таблицю.

Таблиця розділена на 40 штук на стовпчик text. Потім створення індексу на столі займає близько 1 години.

Здається, що індекс MySQL стає дуже повільним, коли розмір таблиці стає дуже великим. А перегородка зменшує таблицю на менші стовбури.


1
Що не так у використанні звичайного CREATE INDEXоператора?

Я б припустив, що це питання може бути кращим для ServerFault - це більше адміністратор БД, ніж питання програмування.
звідти

@Derk: нормальний підхід CREATE INDEX надто повільний. Я повинен виконати завдання протягом 1 дня.

1
Хм ... я не думаю, що ти можеш це обійти. Побудова індексу вимагає від СУБД просканувати всі записи, зібрати їхні "текстові" поля та вставити / змінити відповідні дерева / вузли. А на це потрібно багато часу на 34G ...
chiccodoro

Скільки пам’яті має ваш сервер БД? Ви налаштували MySQL використовувати всю цю пам’ять, чи обмежує вона себе?

Відповіді:


4

Можливо, ваша система просто не вирішує завдання? Я не використовую MySQL (тут SQL Server), але я знаю, що індексує таблицю введення 800 мільйонів. В основному .... для цього вам потрібне відповідне обладнання (як у: багато швидких дисків). Зараз я використовую майже десяток Velociraptors і продуктивність чудова;)

Сервери SQL (не як MS SQL Server, а як сервери баз даних, що використовують SQL) живуть і гинуть з доступом до дисків, а звичайні диски просто не вирішують завдання великих операцій.


Я сумніваюся, що створення індексу зазвичай дуже швидко, якщо кількість записів невелика; скажімо, мільйони. Але коли підрахунок становить мільярди, індекс стає таким повільним. Здається, зростання часу є експоненціальним.

Не слід насправді бути. У MySQL взагалі є обмеження, але це не лайна база даних, і це було б ДУЖЕ погано. Генерація індексу стає повільніше, але через log (n), не (n), тому насправді це не повинно бути БУДЬ.
TomTom

4

Ви можете створити індекс на перших (наприклад, 10) символах текстового поля.

З Документів:

Можна створити індекси, які використовують лише провідну частину значень стовпців, використовуючи синтаксис col_name (length) для визначення довжини префікса індексу:

CREATE INDEX ix_text ON text_page (text(10))

4

Я вирішив проблему, розділивши таблицю.

Таблиця розділена на 40 штук на стовпчик text. Потім створення індексу на столі займає близько 1 години.

Здається, що індекс MySQL стає дуже повільним, коли розмір таблиці стає дуже великим. А перегородка зменшує таблицю на менші стовбури.


Значить, 40 х 1 година менше 10 годин?
symcbean

3

Встановіть sort_buffer_size в 4 Гб (або скільки ви можете, залежно від обсягу пам'яті).

Зараз індекс створення робить щось на зразок, але оскільки у вас є 32MB sort_buffer_size, він в основному обробляє жорсткий диск без потреби.


Ці повідомлення майже з вами прямо не погоджуються: xaprb.com/blog/2010/05/09/how-to-tune-mysqls-sort_buffer_size та краще ronaldbradford.com/blog/… Це здається, що це не глобальне значення, це на запит, так що це 4 Гб за запит, який ви рекомендуєте. Крім того, коли він перевищує 256 Кб, він наближається до диска, а не до фактичної пам'яті. Якщо ви залишаєте його невеликим, це потребує декількох проходів, але це дозволяє уникати диска (він не міняється).
Bra4 Ry4an Brase

3

Якщо вам не потрібно робити запити на зразок:

SELECT page_id FROM text_page WHERE text LIKE '?%';

Я б запропонував створити новий хеш-колонку та індексувати таблицю за стовпцем. Завищений розмір таблиці + індекс може бути значно меншим.

UPD : До речі, 1,4 мільярда цілих чисел первинного ключа займають близько 6 ГБ, тобто середня довжина рядка менше 30 символів, тобто індексація за префіксом може бути більш кращою.

Також слід поглянути на двигун зберігання даних MERGE .


2

Один із способів зробити це - створити нову таблицю з набором індексів і скопіювати дані в нову таблицю.

Крім того, переконайтеся, що у вас є достатньо місця на темп.


1
Я спробував такий підхід. Через 10 годин у нову таблицю було скопійовано менше 1% даних.

1
Чувак ... це 1,4 мільярди записів. Не мільйон, мільярд. Це багато. Мине певний час, незалежно.

Якщо ви вирішите зробити цей метод, розбийте копію на менші шматки. Скажіть від 100 до 200 мільйонів за кожен примірник.

1
@ декомпільований, розбивши його на більш дрібні шматки, нічого не зробить (насправді це може зробити його менш ефективним). @Bryan, Навіть маючи 1,4 мільярда записів, це не повинно зайняти 1000 годин.

0

У випадку, якщо ви все ще цікавитеся, як це зробити найкраще, я б запропонував вам скористатись онлайн-інструментом для зміни таблиці.

В Інтернеті їх дуже багато, однією з відомих є:

У нас такі ж проблеми з великими таблицями (більше 500 мільйонів записів), і зміна іде ідеально. Він створює нову таблицю tmp, додає тригер в оригінальну таблицю (для нового оновлення / видалення / вставки записів) і в середній час копіює всі записи в нову таблицю (з новою структурою)

Удачі!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.