Эффективно читать несколько записей заданного массива идентификаторов записей из базы данных - PullRequest
1 голос
/ 30 июля 2009

Если у вас есть массив идентификаторов записей в коде приложения, каков наилучший способ считывания записей из базы данных?

$idNumsIWant = {2,4,5,7,9,23,56};

Очевидно, что цикл по каждому идентификатору плох, потому что вы делаете n запросов:

foreach ($idNumsIWant as $memID) {
    $DBinfo = mysql_fetch_assoc(mysql_query("SELECT * FROM members WHERE mem_id = '$memID'"));
    echo "{$DBinfo['fname']}\n";
}

Так, может, лучше использовать один запрос?

$sqlResult = mysql_query("SELECT * FROM members WHERE mem_id IN (".join(",",$idNumsIWant).")");
while ($DBinfo = mysql_fetch_assoc($sqlResult))
  echo "{$DBinfo['fname']}\n";

Но масштабируется ли этот метод, когда массив содержит 30 000 элементов?

Как эффективно решить эту проблему?

Ответы [ 5 ]

2 голосов
/ 30 июля 2009

Лучший подход в конечном итоге зависит от количества идентификаторов, которые у вас есть в вашем массиве (вы, очевидно, не хотите отправлять SQL-запрос объемом 50 МБ на ваш сервер, хотя технически он может справиться с ним без особых проблем). ), но в основном о том, как вы собираетесь работать с полученными строками.

  • Если количество идентификаторов очень мало (скажем, несколько тысяч вершин), один запрос с предложением WHERE с использованием синтаксиса IN будет идеальным. Ваш SQL-запрос будет достаточно коротким для надежной, эффективной и быстрой передачи на сервер БД. Этот метод идеально подходит для одного потока, проходящего через результирующие записи.

  • Если число идентификаторов действительно велико, я бы посоветовал вам разбить массив идентификаторов на несколько групп и выполнить более 1 запроса, каждый из которых имеет группу идентификаторов. Это может быть немного тяжелее для сервера БД, но на стороне приложения вы можете порождать несколько потоков и работать с несколькими наборами записей, как только они поступят, параллельно.

Оба метода будут работать.

Cliffnotes: В таких ситуациях сосредотачивайтесь на использовании данных, если извлечение данных не слишком велико из узкого места. И профиль вашего приложения!

1 голос
/ 30 июля 2009

Когда мне приходится иметь дело с такой ситуацией, я вижу как минимум три или четыре возможных решения:

  • один запрос на идентификатор; как вы сказали, это не очень хорошо: много запросов; Я вообще так не делаю
  • используйте предложенное вами решение: один запрос на множество идентификаторов
    • но вы не можете сделать это с очень длинным списком идентификаторов: некоторые движки баз данных имеют ограничение на количество данных, которые вы можете передать в IN()
    • очень большой список в IN() не может быть хорошим с точки зрения производительности
    • Так что я обычно делаю что-то вроде одного запроса X-идентификаторов и повторяю это. Например, чтобы получить данные, соответствующие 1000 идентификаторам, я мог бы сделать 20 запросов, каждый из которых получал данные для 50 идентификаторов (это всего лишь пример: сравнительный анализ вашей БД / таблицы может быть интересным для вашего конкретного случая, поскольку это может зависеть от по нескольким факторам)
  • в некоторых случаях вы также могли бы переосмыслить свои запросы: может быть, вы могли бы избежать передачи такого списка идентификаторов, используя какое-то соединение? (это действительно зависит от того, что вам нужно, от схемы ваших таблиц, ...)

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

Таким образом, вы просто вызываете эту функцию одинаково, и вы всегда получаете одни и те же данные, не беспокоясь о том, как эти данные выбираются; это позволит вам изменить метод выборки, если это необходимо (если вы когда-нибудь найдете другой лучший способ), не нарушая ничего: КАК работает функция, изменится, но, поскольку ее интерфейс (ввод / вывод) останется прежним, он не будет измените вещь для остальной части вашего кода: -)

1 голос
/ 30 июля 2009

Если бы это был я и у меня был такой большой список значений для предложения in, я бы использовал хранимый процесс с переменной, содержащей нужные значения, и использовал бы функцию для отправки их во временную таблицу, а затем присоединиться к нему. В зависимости от размера значений, которые вы хотите отправить, вам может потребоваться разделить его на несколько переменных ввода для обработки. Можно ли каким-либо образом сохранить значения в базе данных (если они часто запрашивают это)? И как пользователь выберет 30 000 значений, конечно же, он или она не собирается их всех опечатывать? Так что, вероятно, есть лучший способ сделать запрос к таблице, основанной на объединении и предложении where.

1 голос
/ 30 июля 2009

Мои мысли:

Первый метод слишком дорог с точки зрения обработки и чтения с диска.

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

0 голосов
/ 14 августа 2009

Используя StringTokenizer, разделив вашу строку на токены, вам будет проще справиться с этим, получая данные для нескольких значений

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...