Как я могу настроить мета таблицы так, чтобы вставка больших наборов данных была эффективной? - PullRequest
3 голосов
/ 25 декабря 2011

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

люди

id | name
==================
1  | John
2  | Suzy
3  | Joe
4  | Laura
5  | Bob

продукты

id  | food       | calories
============================
10  | spaghetti  | 950
11  | meatloaf   | 850
12  | tofu       | 600
13  | cake       | 550

выбор

**people_food**
------------------
1   |  10
2   |  11
3   |  12
4   |  13
5   |  10

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

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

foreach($response as $food)
{
    $food_id = my_mysql_function('select id from foods where food = "spaghetti"');

    if( ! $food_id ){
      $food_id = my_mysql_function_return_query_id( "insert into foods (NULL, '$food')" );
    }

    my_mysql_function( "insert into people_foods ($person_id, $food_id)" );

}

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

Вопросы

С такой схемой,Каков наиболее эффективный способ записать новый ответ и либо получить идентификатор для существующего продукта, либо вставить продукт?Если я добавляю 100 продуктов, я обычно делаю что-то вроде:

$existing = my_mysql_function('select id, food from foods where food in ('.implode($response,',').')');
foreach($existing as $food){
   my_mysql_function_return_query_id( "insert into people_foods ($person_id, '$food['id']')" );
   unset($response[$food]);
}

foreach($response as $food){
 //same code as above mentioned earlier in the question
}

Или, может быть, есть просто другая схема таблицы, которая была бы лучше для выполнения чего-то подобного?

Ответы [ 2 ]

2 голосов
/ 25 декабря 2011

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

Не попадитесь в ловушку оптимизации в ближайшее время илипредположить, что все будет медленно.Сначала попробуйте.

Мне нравятся "настоящие" ключи, поэтому я бы поставил еду в качестве первичного ключа и пропустил идентификатор, но, как вы говорите, присоединение к целым выполняется быстрее.

1 голос
/ 25 декабря 2011

Я не вижу определения для my_mysql_function, my_mysql_function_return_query_id, $person_id и $response.Это далеко не идеально (довольно грязное решение) и может иметь ошибки, поскольку я не проверял его, но должен работать более эффективно.Я надеюсь, что это может привести вас в правильном направлении.

$existing = my_mysql_function('SELECT id FROM foods WHERE food IN (' . implode($response, ', ') . ')');
foreach($existing as $food) {
    my_mysql_function("INSERT INTO people_foods VALUES ($person_id, $food['id'])");
    unset($response[$food]); // Shouldn't this be $response[SOME_INTEGER]?
}

my_mysql_function('INSERT INTO foods VALUES (NULL, ' . implode($response, ', NULL), (NULL, ') . ', NULL)');
my_mysql_function("INSERT INTO people_foods VALUES ($person_id, (SELECT id FROM foods WHERE food='" . implode($response, "')), ($person_id, (SELECT id FROM foods WHERE food='") . "'))");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...