2010-09-03 1 views
2

пожалуйста, у меня такая же проблема, как я нашел здесьMySQL Оптимизация ВЫБРАТЬ из 6 огромных идентичных таблиц с различными данными разделить на метку времени

MySQL - Selecting data from multiple tables all with same structure but different data,

я должен выбрать данные из нескольких таблиц MySQL с идентичную структуру, но разные данные (разбиваются на таблицы_0, table_1, table_2 и т. д. на таблицу_5, чтобы распределять миллионы записей данных).

Аппаратное обеспечение, создающее записи данных для каждого устройства, перемещается из таблицы в таблицу в соответствии с полем timestamp, которое НЕ является уникальным. например 50 записей в таблице_0 могут иметь одинаковую метку времени. Когда данные попадают в конец таблицы_5, он возвращается к таблице_0, чтобы начать переписывание данных там. Мне нужно получить данные на каждом устройстве за определенный промежуток времени.

столбцов данных Каждая таблица (для table_0, table_1 ... до table_5):
timestamp, robotGroupID, robotID, sensor1, sensor2, sensor3, ... (many of them)

Однако таблицы ОГРОМНЫ и UNION ALL (я прочитал его быстрее, чем DISTINCT) принимает навсегда для выполнения , даже с двумя таблицами, не говоря уже о 6. Например Я проиллюстрирую две таблицы ниже.

заявление MySQL в PHP: (показано только для датчика 1, датчик 2 и датчик 3)
(SELECT sensor1, sensor2, sensor3 FROM table_0 WHERE robotID=".$robotID." AND timestamp BETWEEN ".$timeStampStart." AND ".$timeStampStop)
UNION ALL
(SELECT sensor1, sensor2, sensor3 FROM table_1 WHERE robotID=".$robotID." AND timestamp BETWEEN ".$timeStampStart." AND ".$timeStampStop)

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

Я не могу использовать LIMIT, потому что количество отчетов от роботов в каждом временном диапазоне неизвестно заранее. Я не могу использовать MERGE STORAGE ENGINE, потому что у меня есть доступ только для чтения к базе данных компании.

У меня есть идея использовать count (robotID) или около того на каждой таблице, чтобы проверить перед запуском запросов, но я не уверен, как это сделать, потому что я довольно новичок.

Пожалуйста, как вы думаете, что я могу сделать эту работу быстрее для 6 таблиц и многих других столбцов, так как есть много столбцов, чем показано? Заранее спасибо!

+0

- временная метка проиндексирована? вы могли бы предоставить EXPLAIN запроса, размещенного – ejrowley

+0

Спасибо, ejrowley. Я не знал, что такое EXPLAIN, но я искал его и сделал то, что нашел там. Это то, что вам нужно? N.B. В таблицах нет первичных ключей. ------------------------------------------------- ------------------ стол: table_0 | Тип: диапазон | Возможные_блоки: IDX_TIME_UQ | key: IDX_TIME_UQ | key_len \t ref: 8 | строки: 488590 | Дополнительно: использование, где --------------------------------------------- ---------------------- стол: table_1 | Тип: диапазон | Возможные_блоки: IDX_TIME_UQ | key: IDX_TIME_UQ | key_len \t ref: 8 | строки: 675489 | Дополнительно: использование где – Cogicero

+0

Сколько результатов вы ожидаете от запроса, это множество разных robotID или только несколько. Кроме того, как быстро, условно говоря, это запрос, когда он просто запускается на table_1. – ejrowley

ответ

0

Должен признаться, что я все еще новичок PHP/MySQL кодер, но со многими идеями; поэтому мой код, вероятно, «грязный».

Так что я решил проблему таким образом, чтобы двигаться вперед, но, пожалуйста, лучшие решения приветствуются. Что касается любого странного синтаксиса, я использую класс базы данных, основанный на PHP PDO, потому что я использую много разных типов RBDMS для этого проекта.

Для переменной $ myQuery_start, я добавил имена других столбцов, а также датчики с 1 по 3.
$myQuery_start = "(SELECT sensor1, sensor2, sensor3 FROM ";
$myQueryCount_start = "(SELECT COUNT(*) FROM ";
$myQuery_stop = " WHERE robotID=".$robotID." AND timestamp BETWEEN ".$timeStampStart." AND ".$timeStampStop.")";

$count_0 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_0".$myQuery_stop)->fetchColumn();
$count_1 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_1".$myQuery_stop)->fetchColumn();
$count_2 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_2".$myQuery_stop)->fetchColumn();
$count_3 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_3".$myQuery_stop)->fetchColumn();
$count_4 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_4".$myQuery_stop)->fetchColumn();
$count_5 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_5".$myQuery_stop)->fetchColumn();

И теперь я могу проверить, нуждается ли UNION ALL быть приложены к каждому запроса таблицы или нет. Нет необходимости иметь UNION ALL, если в следующей таблице нет записи данных.
$union_0 = (($count_1 + $count_2 + $count_3 + $count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_1 = (($count_2 + $count_3 + $count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_2 = (($count_3 + $count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_3 = (($count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_4 = (($count_5) > 0)?" UNION ALL ":"";

и теперь мы создаем запросы таблиц и объединяются, чтобы сформировать полную QUERY

$query_0 = ($count_0 > 0)?$myQuery_start."ip_minute_stats_0".$myQuery_stop.$union_0:"";
$query_1 = ($count_1 > 0)?$myQuery_start."ip_minute_stats_1".$myQuery_stop.$union_1:"";
$query_2 = ($count_2 > 0)?$myQuery_start."ip_minute_stats_2".$myQuery_stop.$union_2:"";
$query_3 = ($count_3 > 0)?$myQuery_start."ip_minute_stats_3".$myQuery_stop.$union_3:"";
$query_4 = ($count_4 > 0)?$myQuery_start."ip_minute_stats_4".$myQuery_stop.$union_4:"";
$query_5 = ($count_5 > 0)?$myQuery_start."ip_minute_stats_5".$myQuery_stop:"";

Затем сцепляются:
$myQuery = $query_0.$query_1.$query_2.$query_3.$query_4.$query_5;
И, наконец, $ myQuery выполняется, чтобы производить все данные по мере необходимости.

По крайней мере, это примерно в 8 раз быстрее, чем предыдущий способ я использовал UNION ALL, так что я думаю, что это справедливо. Любая предлагаемая дальнейшая оптимизация?

+0

Пожалуйста, больше ответов (или изменений по вышеуказанному ответу) приветствуются. Мой босс все еще думает, что это происходит слишком медленно :(Я хочу знать, что я старался изо всех сил, прежде чем двигаться дальше. Спасибо. – Cogicero

1

ли поля RobotID и Отметка индексируются?

Я хотел бы добавить индекс мульти-поля (RobotId, метки времени), по крайней мере.

Вы говорите, что вы прочитали только доступ к таблицам, так что вы можете запросить этот индекс будет добавлен? Я уверен, что это поможет как в ваших оригинальных, так и в обновленных запросах.

+0

Большое спасибо Дэйв Рикс. Но нет, многие компании используют эту же базу данных, поэтому просьба моей компании была категорически отвергнута. Хотелось бы добавить такой индекс! Благодаря :) – Cogicero

0

Если вы можете убедить их, чтобы изменить структуру базы данных, вы можете значительно оптимизировать расположение базы данных с помощью MySQL секционирования. Вы захотите изучить «Разделение разделов» и настроить правила секционирования, которые позволят MySQL автоматически сортировать ваши данные в невидимые субтитры для ускорения результатов SELECT. Вам даже не понадобится несколько таблиц.

См. http://dev.mysql.com/doc/refman/5.1/en/partitioning-overview.html