2014-01-22 2 views
0

У меня есть чрезвычайно большая таблица ~ миллиард строк.PHP - оптимизировать SQL, выбрать несколько строк для очень БОЛЬШОЙ таблицы

foreach($idArray as $id){ 
    'SELECT DIE_X, DIE_Y, LOG_INDEX, TREND_ELEMENT, TREND_DATA FROM trend_data_level_5 WHERE TREND_INDEX =' $id; 
    $result = mysql_query($query); 
} 

Этот подход занимает много времени, так как мой стол становится все больше и больше. Я использую механизм innoDB для моей базы данных SQL.

Я запустил таймер, и указанная выше петля взяла ~ 17 секунд для стола размером ~ 15 милион. Представьте себе, как долго это займет миллиардные ряды!

Могу ли я получить это время значительно? Если да, то какой лучший подход?

EDIT: Вот то, что таблица выглядит

------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Table    | Create Table 
                                       | 
+--------------------+-------------------------------------------------------------------------------------------------------------------------------- 
------------------------------------------------------------------------------------------------------------------------------------------------+ 
| trend_data_level_5 | CREATE TABLE trend_data_level_5 (
    LOG_INDEX int(5) DEFAULT NULL, 
    DIE_X int(3) DEFAULT NULL, 
    DIE_Y int(3) DEFAULT NULL, 
    TREND_INDEX int(10) DEFAULT NULL, 
    TREND_ELEMENT varchar(3) DEFAULT NULL, 
    TREND_DATA int(5) DEFAULT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 | 
+--------------------+-------------------------------------------------------------------------------------------------------------------------------- 
------------------------------------------------------------------------------------------------------------------------------------------------+ 
+0

Является ли «ID» ключом на столе? или, по крайней мере, проиндексированы? Насколько велика «ID» (int, varchar и т. Д.). Предполагая, что он проиндексирован, у вас достаточно памяти на машине для загрузки всего индекса? –

+0

Измените свое сообщение и добавьте вывод 'SHOW CREATE TABLE table_1', чтобы мы могли видеть его столбцы, типы данных и индексы. –

+0

Хорошо, я внес соответствующие изменения. Проверьте структуру таблицы –

ответ

0

Прежде всего, я бы использовал расширение MYSQLI. Более подробную информацию здесь: MySqli manual

Во-вторых, я не знаю, сколько элементов может иметь $idArray массив, но вы можете сделать предложение так:

$list = implode(",", $idArray); 
$query = "SELECT DIE_X, DIE_Y, LOG_INDEX, TREND_ELEMENT, TREND_DATA FROM trend_data_level_5 WHERE TREND_INDEX IN ($list)"; 
$stmt = $your_mysqli_object->prepare($query); 
$stmt->execute(); 
$stmt->store_result(); // This releases the real transaction and charges the data to PHP 

while($stmt->fetch()) 
{ 
    //... 
} 

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

Надеюсь, я помог вам. Сообщите мне, если он работает правильно или если вы нашли лучшее решение. Я тоже хочу учиться!

+0

Запрос 'SELECT IN', кажется, выполняется намного быстрее, чем выполнение отдельных запросов в цикле. Я действительно не смотрел в mysqli. Обеспечивает ли она улучшенную производительность запросов? –

+0

Ну, это более чистый вид кода, потому что он объектно ориентирован. Но я этого не исследовал. Я думаю, что это должно быть, потому что не слишком старо, и я предполагаю, что это правильно и оптимизировано. –

+0

Взгляните на это сообщение: http://stackoverflow.com/questions/548986/mysql-vs-mysqli-in-php –

0

Если trend_index является первичным ключом использовать в качестве так. В противном случае создайте индекс, используя trend_index: CREATE INDEX B ON T1 (B);

Если это уникально, сделайте так CREATE UNIQUE INDEX C ON T1 (C);

Для простого запроса, которого должно быть достаточно.

0

Это очень простой вопрос. Ответ заключается в использовании индексов (у вас их нет), и в Интернете есть много ресурсов, которые помогут вам понять, как это сделать.

0

Я бы предложил использовать PDO. Тогда вам придется использовать один готовый запрос (запросы в цикле - очень плохая практика, так как это очень медленно!), Тогда вы сделаете $pdo->fetchAll(), что принесет вам двумерный массив (или массив массивов, если вы хотеть). Затем вы можете безопасно выполнить свой foreach через этот массив.
Сообщите мне, если вам нужны дополнительные объяснения.

Смежные вопросы