Совет по денормализации

У меня есть база данных школьных округов (примерно 15 000 из них и число их увеличивается) и пенсионные планы/льготы, доступные сотрудникам каждого из них. Данные довольно хорошо нормализованы:

  • Запись округа связана с 0 или n вариантами пенсионного плана (где n ‹ 10 распределены по 3 объединенным таблицам).
  • Запись округа связана с 0 или n льготами (где n ближе к 40 из 1 объединенной таблицы).
  • Район также связан с несколькими другими вещами, где количество ассоциаций является номинальным.

Теперь клиент хочет сообщить. И они хотят сообщать очень динамично (подумайте об интеллектуальном плейлисте iTunes, в котором можно добавлять/удалять правила для любой собственности любого района, плана или льготы). Мне нужно разрешить им запрашивать любую собственность округа, его пенсионные планы или льготы и возвращать все.

Чтобы не усложнять (на данный момент) и избежать дублирования данных, я настроил пару представлений (тсссс, я знаю), которые просто позволяют мне получать доступ к данным таким образом, что любая запись 1 района фактически имеет 1- отношение к 1 с представлением all_retirement_plans и запись 1 к 1 с представлением all_benefits_plans. Это дает мне чистый набор объединений, который приводит к унифицированному набору результатов, но, очевидно, имеет свой собственный набор проблем, с которыми я столкнусь раньше, чем позже...

А именно, по мере добавления новых данных он будет работать смехотворно медленно.

Я ищу несколько советов по денормализации. Я думал о таблице отчетов, которая делает то же, что и представления, но может быть проиндексирована. Я также подумал о том, чтобы сбросить весь этот набор данных о районах в MongoDB (или аналогичный). Я уверен, что есть и другие варианты, но я буду играть методом проб и ошибок, поэтому я надеюсь, что кто-то здесь может посоветовать мне способ, который поможет мне найти разумное решение.

Суть в том, что мне нужно иметь возможность хранить около 15 000 (и растущих) записей по районам вместе с большим количеством дополнительных метаданных, а затем создавать отчеты по этим данным на очень детальном уровне. У кого-нибудь есть какие-нибудь мысли или советы помимо того, куда меня завели мои собственные размышления? Я пытаюсь опередить проблемы, которые, как я знаю, грядут.


person Rob Wilkerson    schedule 20.02.2013    source источник
comment
Я настроил пару представлений (тссс, я знаю)... Представления — это фундаментальная функция систем управления базами данных SQL. Когда вам нужно использовать views и shhh рядом друг с другом, вам следует подумать о переключении на другую СУБД.   -  person Mike Sherrill 'Cat Recall'    schedule 20.02.2013
comment
Я был немного глуп, но дело в том, что представления, вероятно, не являются подходящей платформой для этой конкретной потребности. Учитывая размер данных (в частности, количество денормализованных столбцов), представления работают примерно так же медленно, как я и ожидал. Я не знаю, как их оптимизировать, но хотелось бы ошибаться.   -  person Rob Wilkerson    schedule 20.02.2013
comment
Один из способов повысить производительность — переключиться на СУБД с лучшим оптимизатором запросов.   -  person Mike Sherrill 'Cat Recall'    schedule 21.02.2013
comment
Итак, эти представления all_retirement_plans и all_benefits_plans используют GROUP_CONCAT для агрегирования и объединения всех разных строк?   -  person ruakh    schedule 21.02.2013
comment
@ruakh - Если я понимаю ваш вопрос, то нет. Конкатенация строк не происходит. У меня нет перед собой точных цифр, но в каждом округе может быть 0 или более из ~30 различных пособий, а запись о пособии имеет несколько свойств. Представление all_benefits_pans содержит запись округа, содержащую каждое свойство каждого преимущества. Он добавляет до ~ 100 столбцов.   -  person Rob Wilkerson    schedule 21.02.2013
comment
О, так ты исполняешь что-то вроде PIVOT?   -  person ruakh    schedule 21.02.2013
comment
Нет. Я пока ничего необычного не делаю. Я бросил это как быстрое временное решение, чтобы они начали. Это прямое представление, которое объединяет несколько таблиц, включая одну таблицу (benefits), много раз.   -  person Rob Wilkerson    schedule 21.02.2013
comment
Под своего рода PIVOT я подразумеваю концептуальный поворот. MySQL не поддерживает фактическое ключевое слово PIVOT, но вы можете использовать большое количество JOIN для достижения примерного эффекта PIVOT.   -  person ruakh    schedule 22.02.2013


Ответы (1)


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

Некоторые варианты переноса данных в Mongo:

  1. Вы можете легко просто записывать данные из MySQL в Mongo и сохранять свои реляционные таблицы. Никаких преобразований, просто перемещайте данные прямо. В Mongo есть map/reduce, которые можно вывести в новую коллекцию. Хотя это медленно. =( Если вы переместите представление прямо, у Mongo есть структура агрегации, которая очень мощна для создания новых документов.

  2. В идеале вы должны составить свой «документ» в MySQL, а затем переместить его. Мой опыт работы с MySQL заключается в том, чтобы сделать документ очень плоским. Вы можете добавить структуру, проявив творческий подход с помощью group_concat. Вы в основном группируете некоторые данные и ручные строки JSON вместе. (Некрасиво, но работает)

  3. Mongo отлично работает с документами. Действительно, очень здорово. Я настоятельно рекомендую его, если вы хотите работать с денормализованными данными.

  4. Это может быть излишним, но мы используем Mule ESB для перемещения данных из MySQL в Mongo. Вы можете делать там более сложные/хитрые преобразования, но есть кривая обучения.

  5. В SQL Server вы можете выводить запросы в виде XML. Если вы можете найти библиотеку для этого в MySQL, то переход от XML к JSON будет простым. Мы смогли выполнять запросы в SQL Server более чем по 100 тыс. записей и очень быстро выводить XML.

Дайте мне знать, если вы хотите получить более подробную информацию по любому из пунктов. знак равно

person ryan1234    schedule 22.02.2013
comment
Спасибо, Райан. Сначала я хотел убедиться, что даже если я перейду на Mongo, я все равно смогу выполнять очень детализированные запросы. Документ MongoDB будет представлять район (включая все данные о его пенсионном плане/пособиях), поэтому я мог бы либо включить их как вложенные компоненты, либо сгладить все это, как вы упомянули. Похоже, плоский быстрее? Я должен изучить group_concat. - person Rob Wilkerson; 23.02.2013
comment
Flat легче перенести с MySQL на Mongo. Mongo имеет очень богатый язык запросов. К синтаксису может потребоваться некоторое время, чтобы привыкнуть к нему, но вы определенно можете добиться многого. group_concat может создавать массивы или вложенные документы. - person ryan1234; 23.02.2013
comment
Наконец-то посмотрел group_concat. Это не совсем то, что у меня есть. Я не столько объединял значения полей, сколько сглаживал записи. Если у округа может быть 3 возможных записи о льготах (каждая с идентификатором и поставщиком), я свел каждую из этих записей о льготах в представление, чтобы у округа теперь была 1 запись о льготах с полями с префиксом для различения. Например, accident_insurance_id, accident_insurance_provider, dental_id, dental_provider и т. д. Теперь моя таблица districts имеет связь 1-к-1 с этим представлением. - person Rob Wilkerson; 25.02.2013
comment
Я думаю, что моей первоначальной мыслью было сгладить district, чтобы документ округа включал всю информацию о пенсионном плане и пенсионных планах в документе MongoDB. Каждый районный документ будет довольно большим (около 150 объектов или около того), и их будет 15-20 тысяч, и их количество будет увеличиваться. Какие-то красные флажки в этом предположении с точки зрения производительности? - person Rob Wilkerson; 25.02.2013
comment
Да, некоторые вещи, которые следует отметить с Mongo и документами/размером документа. Mongo имеет ограничение в 16 МБ для документов. Вы не можете пройти через это. Также у Mongo есть тонкое предположение, что ваш документ не будет слишком сильно расти. Если он становится слишком большим, Mongo должен переместить его из текущего места в памяти и найти новое место. Это может вызвать фрагментацию вашей оперативной памяти и замедлить работу. Если какие-то ваши данные часто меняются, я бы, наверное, рекомендовал сослаться на них ссылкой, а не встраивать в основной документ. - person ryan1234; 26.02.2013