Что такое хороший способ денормализации базы данных mysql?
У меня есть большая база данных нормализованных данных порядка, которая становится очень медленной для запроса отчетов. Многие из запросов, которые я использую в отчетах, объединяются в пять или шесть таблиц, и им приходится изучать десятки или сотни тысяч строк.
есть много запросов, и большинство из них были оптимизированы как можно больше, чтобы уменьшить нагрузку на сервер и увеличить скорость. Я думаю, что пора начать хранить копию данных в денормализованной форме.
любые идеи по подход? Должен ли я начать с пары моих худших вопросов и идти оттуда?
8 ответов
Я знаю больше о mssql, что mysql, но я не думаю, что количество соединений или количество строк, о которых вы говорите, должно вызвать у вас слишком много проблем с правильными индексами на месте. Вы проанализировали план запроса, чтобы увидеть, если вы пропускаете какие-то?
http://dev.mysql.com/doc/refman/5.0/en/explain.html
при этом, как только вы насытитесь своими индексами и исчерпаете все другие пути, де-нормализация может быть правильной ответ. Если у вас есть только один или два запроса, которые являются проблемами, вероятно, подходит ручной подход, в то время как какой-то инструмент хранения данных может быть лучше для создания платформы для разработки кубов данных.
вот сайт, который я нашел, который затрагивает эту тему:
http://www.meansandends.com/mysql-data-warehouse/?link_body%2Fbody=%7Bincl%3AAggregation%7D
вот простой метод, который вы можете использовать для сохранения денормализации запросов просто, если вы просто делаете несколько за раз (и я не заменяю ваши таблицы OLTP, просто создаю новую для целей отчетности). Предположим, у вас есть этот запрос в вашем приложении:
select a.name, b.address from tbla a
join tblb b on b.fk_a_id = a.id where a.id=1
вы можете создать денормализованную таблицу и заполнить почти тот же запрос:
create table tbl_ab (a_id, a_name, b_address);
-- (types elided)
обратите внимание, что подчеркивания соответствуют псевдонимам таблицы, которые вы используете
insert tbl_ab select a.id, a.name, b.address from tbla a
join tblb b on b.fk_a_id = a.id
-- no where clause because you want everything
затем, чтобы исправить приложение, чтобы использовать новую денормализованную таблицу, переключите точки для подчеркивания.
select a_name as name, b_address as address
from tbl_ab where a_id = 1;
для огромных запросов это может сэкономить много времени и дает понять, откуда данные пришли, и вы можете повторно использовать запросы, которые у вас уже есть.
помните, я выступаю только в качестве последнего средства. Держу пари, есть несколько индексов, которые помогут вам. И когда вы де-нормализуете, не забудьте учитывать дополнительное пространство на ваших дисках и выяснить, когда вы запустите запрос для заполнения новых таблиц. Это, вероятно, должно быть ночью, или когда-нибудь активность низкая. И данные в этой таблице, конечно, никогда не будут точно актуальными.
[еще одно редактирование] не забывайте, что новые таблицы, которые вы создаете, также должны быть индексированы! Хорошая часть заключается в том, что вы можете индексировать содержимое своего сердца и не беспокоиться о блокировке обновлений, так как помимо вашей массовой вставки таблица будет видеть только выбор.
в соответствии с некоторыми другими комментариями, я бы определенно посмотрел на вашу индексацию.
одна вещь, которую я обнаружил в начале этого года в наших базах данных MySQL, была сила составных индексов. Например, если вы отчитываетесь о номерах заказов по диапазонам дат, может помочь составной индекс в Столбцах номер заказа и дата заказа. Я считаю, что MySQL может использовать только один индекс для запроса, поэтому, если бы у вас были отдельные индексы на номере заказа и дате заказа, он имел бы выбрать только один из них. Использование команды EXPLAIN может помочь определить это.
чтобы дать представление о производительности с хорошими индексами (включая многочисленные составные индексы), я могу запускать запросы, соединяющие 3 таблицы в нашей базе данных и получать почти мгновенные результаты в большинстве случаев. Для более сложных отчетов большинство запросов выполняется менее чем за 10 секунд. Эти 3 таблицы имеют 33 миллиона, 110 миллионов и 140 миллионов строк соответственно. Обратите внимание, что мы также уже нормализовали это немного ускорит наш самый распространенный запрос по базе данных.
дополнительная информация о ваших таблицах и типах запросов отчетов может позволить дальнейшие предложения.
Я знаю, что это немного касательно, но вы пытались увидеть, есть ли больше индексов, которые вы можете добавить?
У меня не так много фона БД, но в последнее время я много работаю с базами данных, и я обнаружил, что многие запросы можно улучшить, просто добавив индексы.
мы используем DB2, и есть команда под названием db2expln и db2advis, первая будет указывать, используются ли сканирование таблиц и сканирование индексов, а вторая будет рекомендовать индексы можно добавить для повышения производительности. Я уверен, что MySQL имеет аналогичные инструменты...
в любом случае, если это то, что вы еще не рассмотрели, это очень помогло мне... но если вы уже прошли этот маршрут, то я думаю, это не то, что вы ищете.
другой возможностью является "материализованное представление" (или, как его называют в DB2), которое позволяет указать таблицу, которая по существу построена из частей из нескольких таблиц. Таким образом, вместо нормализации фактического столбцы, вы можете предоставить это представление для доступа к данным... но я не знаю, оказывает ли это серьезное влияние на производительность вставок/обновлений/удалений (но если он "материализован", то он должен помочь с выбором, поскольку значения физически хранятся отдельно).
MySQL 5 поддерживает вид, что может быть полезно в этом сценарии. Похоже, вы уже сделали много оптимизации, но если нет, вы можете использовать MySQL объяснить синтаксис, чтобы увидеть, какие индексы используются и то, что тормозит ваши запросы.
Что касается нормализации данных (используете ли вы представления или просто дублируете данные более эффективным способом), я думаю, начиная с самых медленных запросов и работая по-своему through-хороший подход.
для MySQL мне нравится этот разговор:Real World Web: Производительность И Масштабируемость, MySQL Edition. Это содержит много различных советов для получения большей скорости из MySQL.
вы также можете рассмотреть возможность выбора во временную таблицу, а затем выполнения запросов к этой временной таблице. Это позволит избежать необходимости воссоединения таблиц для каждого отдельного запроса (при условии, что вы можете использовать временную таблицу для многочисленных запросов, конечно). Это в основном дает вам денормализованные данные, но если вы выполняете только вызовы select, нет никаких проблем с согласованностью данных.
в дополнение к моему предыдущему ответу, другой подход, который мы приняли в некоторых ситуациях для хранения ключевых данных отчетности в виде отдельных сводных таблиц. Есть определенные запросы отчетности, которые просто будут медленными даже после денормализации и оптимизации, и мы обнаружили, что создание таблицы и хранение текущих итогов или сводной информации в течение месяца, когда она пришла, сделали отчет в конце месяца намного быстрее.
мы нашли этот подход легко реализовать, как это не сломал ничего, что уже работало - это просто дополнительные вставки базы данных в определенные моменты.
Я играл с составными индексами и видел некоторые реальные преимущества...может быть, я настрою некоторые тесты, чтобы увидеть, может ли это спасти меня здесь...по крайней мере, немного дольше.