Выполнение запросов к тысячам баз данных MySQL с одинаковой схемой

#mysql #database #scalability

#mysql #База данных #масштабируемость

Вопрос:

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

Вот пример того, что я хотел бы сделать:

SELECT something FROM db_prefix_*.tablename WHERE something = 1;

… и пусть он вернет один набор результатов, db_prefix_ * — это имя базы данных.

Существует ли что-нибудь подобное или я сплю?

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

Комментарии:

1. AFAIK, такого нет — как насчет объединения баз данных в одну большую базу данных?

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

Ответ №1:

Это то, что вы ищете:

 DECLARE @sqlQuery nvarchar(MAX)
SET @sqlQuery=''
select @sqlQuery=@sqlQuery 'select something from '  SCHEMA_NAME   '.tableName' from INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME LIKE 'db_prefix_%'
print @sqlQuery
EXEC sp_executeSQL @sqlQuery
 

Я работаю на сервере SQL Server, и я изо всех сил старался перевести MySQL, пожалуйста, поправьте меня, если что-то здесь неверно.

Комментарии:

1. «У меня есть десятки тысяч баз данных MySQL на одном сервере»

Ответ №2:

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

Ответ №3:

Вы можете попробовать Parallel::ForkManager, который предоставляет «простой менеджер разветвлений параллельной обработки» для perl.

Вы можете изменять максимальное количество процессов вверх и вниз в зависимости от того, насколько тяжелым является запрос, а также использовать nice / ionice для предотвращения чрезмерной нагрузки на сервер.

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

Ответ №4:

Короткий ответ — нет: все драйверы php mysql (afaik) обрабатывают соединения с базами данных независимо, как вы уже делаете, перебирая их. Даже если бы был какой-то драйвер, который допускал нужный вам синтаксис, я почти уверен, что он все равно создавал бы новое соединение для каждой базы данных на каком-то уровне из-за самого mysql.

Длинный ответ — да: вы можете создать индекс для нескольких БД. Наличие одной и той же схемы в нескольких базах данных по сути является сегментированием, так что это известная проблема (хотя уникальность первичного ключа может быть проблемой). Если вы создадите индекс something для нескольких баз данных, вы сможете получить производительность в реальном времени, особенно если вам нужны только значения индексированных полей. Twitter сообщает об успехе с индексами в таблицах mysql на ранней стадии (http://engineering.twitter.com/2011/05/engineering-behind-twitters-new-search.html ) так что есть обнадеживающий прецедент. Сегментирование mysql было (возможно) более продуктивным в сообществе Rails, чем в сообществе PHP (http://planet.mysql.com/?tag_search=2013 ) так что вы можете найти там несколько советов.

Недавно столкнувшись с аналогичной масштабируемой проблемой, мы просто перешли на Mongo.