Который более эффективен: Несколько таблиц MySQL или одна большая таблица?

Перепишите теперь удаленного ответа VonC.

Сжатый ответ Robert Gamble имеет дело непосредственно с вопросом. Этот распространяется о некоторых проблемах с именами файлов, содержащими пробелы.

См. также: $ {1: $ +" "} в/bin/sh

Основной тезис: "$@" корректно, и $* (закрывший кавычки) является почти всегда неправильным. Это вызвано тем, что "$@" хорошо работает, когда аргументы содержат пробелы и работы то же как $* когда они не делают. При некоторых обстоятельствах, "$*" в порядке также, но "$@" обычно (но не всегда) работает в тех же местах. Неупомянутый, $@ и $* эквивалентны (и почти всегда неправильно).

Так, между чем различие $*, $@, "$*", и "$@"? Они все связаны с 'всеми аргументами оболочке', но они делают разные вещи. При закрытии кавычки, $* и $@ сделайте то же самое. Они рассматривают каждое 'слово' (последовательность непробела) как отдельный аргумент. Заключенные в кавычки формы очень отличаются, хотя: "$*" рассматривает список аргументов как единственную разделенную пробелом строку, тогда как "$@" рассматривает аргументы почти точно, как они были при определении на командной строке. "$@" не расширяется ни до чего вообще, когда нет никаких позиционных параметров; "$*" расширяется до пустой строки — и да, существует различие, хотя может быть трудно чувствовать его. Посмотрите больше информации ниже после введения (нестандартной) команды al.

Вторичный тезис: если необходимо обработать споры с пробелами и затем передать их на другие команды, то Вам иногда нужны нестандартные инструменты для помощи. (Или необходимо использовать массивы, тщательно: "${array[@]}" ведет себя аналогично к "$@".)

Пример:

    $ mkdir "my dir" anotherdir
    $ ls
    anotherdir      my dir
    $ cp /dev/null "my dir/my file"
    $ cp /dev/null "anotherdir/myfile"
    $ ls -Fltr
    total 0
    drwxr-xr-x   3 jleffler  staff  102 Nov  1 14:55 my dir/
    drwxr-xr-x   3 jleffler  staff  102 Nov  1 14:55 anotherdir/
    $ ls -Fltr *
    my dir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 my file

    anotherdir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 myfile
    $ ls -Fltr "./my dir" "./anotherdir"
    ./my dir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 my file

    ./anotherdir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 myfile
    $ var='"./my dir" "./anotherdir"' && echo $var
    "./my dir" "./anotherdir"
    $ ls -Fltr $var
    ls: "./anotherdir": No such file or directory
    ls: "./my: No such file or directory
    ls: dir": No such file or directory
    $

Почему это не работает? Это не работает, потому что оболочка обрабатывает кавычки, прежде чем это развернет переменные. Так, чтобы заставить оболочку обращать внимание на кавычки, встроенные в $var, необходимо использовать eval:

    $ eval ls -Fltr $var
    ./my dir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 my file

    ./anotherdir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 myfile
    $ 

Это становится действительно хитрым, когда у Вас есть имена файлов такой как"He said, "Don't do this!""(с кавычками и двойными кавычками и пробелами).

    $ cp /dev/null "He said, \"Don't do this!\""
    $ ls
    He said, "Don't do this!"       anotherdir                      my dir
    $ ls -l
    total 0
    -rw-r--r--   1 jleffler  staff    0 Nov  1 15:54 He said, "Don't do this!"
    drwxr-xr-x   3 jleffler  staff  102 Nov  1 14:55 anotherdir
    drwxr-xr-x   3 jleffler  staff  102 Nov  1 14:55 my dir
    $ 

Оболочки (все они) не делают особенно легким обработать такой материал, таким образом (странно достаточно) много программ Unix не делают хорошего задания обработки их. На Unix имя файла (единственный компонент) может содержать любые символы кроме наклонной черты и NUL '\0'. Однако оболочки сильно не поощряют пробелов или новых строк или вкладок нигде в пути. Это также, почему стандартные имена файлов Unix не содержат пробелы и т.д.

При контакте с именами файлов, которые могут содержать пробелы и другие неприятные символы, необходимо быть чрезвычайно осторожными, и я нашел давно, что мне была нужна программа, которая не является стандартной на Unix. Я называю его escape (версия 1.1 была датирована 1989-08-23T16:01:45Z).

Вот пример escape используемый - с системой управления SCCS. Это - сценарий покрытия, который делает обоих a delta (думайте регистрация), и a get (думайте контроль). Различные аргументы, особенно -y (причина, почему Вы внесли изменение) будет содержать пробелы и новые строки. Обратите внимание, что даты сценария с 1992, таким образом, это использует обратные галочки вместо $(cmd ...) нотация и не использует #!/bin/sh на первой строке.

:   "@(#)$Id: delget.sh,v 1.8 1992/12/29 10:46:21 jl Exp $"
#
#   Delta and get files
#   Uses escape to allow for all weird combinations of quotes in arguments

case `basename $0 .sh` in
deledit)    eflag="-e";;
esac

sflag="-s"
for arg in "$@"
do
    case "$arg" in
    -r*)    gargs="$gargs `escape \"$arg\"`"
            dargs="$dargs `escape \"$arg\"`"
            ;;
    -e)     gargs="$gargs `escape \"$arg\"`"
            sflag=""
            eflag=""
            ;;
    -*)     dargs="$dargs `escape \"$arg\"`"
            ;;
    *)      gargs="$gargs `escape \"$arg\"`"
            dargs="$dargs `escape \"$arg\"`"
            ;;
    esac
done

eval delta "$dargs" && eval get $eflag $sflag "$gargs"

(Я, вероятно, не использовал бы Escape вполне так полностью в эти дни - это не нужно с -e аргумент, например - но в целом, это - одно из моего более простого использования сценариев escape.)

escape программа просто производит свои аргументы, скорее как echo делает, но это гарантирует, что аргументы защищены для использования с eval (один уровень eval; У меня действительно есть программа, которая сделала удаленное выполнение оболочки, и это должно было выйти из вывода escape).

    $ escape $var
    '"./my' 'dir"' '"./anotherdir"'
    $ escape "$var"
    '"./my dir" "./anotherdir"'
    $ escape x y z
    x y z
    $ 

У меня есть другая названная программа al это перечисляет его аргументы один на строку (и это является еще более древним: версия 1.1, датированная 1987-01-27T14:35:49). Это является самым полезным при отладке сценариев, поскольку это может быть включено в командную строку для наблюдения, какие аргументы на самом деле передаются команде.

    $ echo "$var"
    "./my dir" "./anotherdir"
    $ al $var
    "./my
    dir"
    "./anotherdir"
    $ al "$var"
    "./my dir" "./anotherdir"
    $

[Добавленный: И теперь показать различие между различным "$@" нотации, вот еще один пример:

$ cat xx.sh
set -x
al $@
al $*
al "$*"
al "$@"
$ sh xx.sh     *      */*
+ al He said, '"Don'\''t' do 'this!"' anotherdir my dir xx.sh anotherdir/myfile my dir/my file
He
said,
"Don't
do
this!"
anotherdir
my
dir
xx.sh
anotherdir/myfile
my
dir/my
file
+ al He said, '"Don'\''t' do 'this!"' anotherdir my dir xx.sh anotherdir/myfile my dir/my file
He
said,
"Don't
do
this!"
anotherdir
my
dir
xx.sh
anotherdir/myfile
my
dir/my
file
+ al 'He said, "Don'\''t do this!" anotherdir my dir xx.sh anotherdir/myfile my dir/my file'
He said, "Don't do this!" anotherdir my dir xx.sh anotherdir/myfile my dir/my file
+ al 'He said, "Don'\''t do this!"' anotherdir 'my dir' xx.sh anotherdir/myfile 'my dir/my file'
He said, "Don't do this!"
anotherdir
my dir
xx.sh
anotherdir/myfile
my dir/my file
$

Заметьте, что ничто не сохраняет исходные пробелы между * и */* на командной строке. Кроме того, обратите внимание, что можно изменить 'параметры командной строки' в оболочке при помощи:

set -- -new -opt and "arg with space"

Это устанавливает 4 опции,'-new', '-opt', 'and', и'arg with space'.
]

Хм, это - вполне длинный ответ - возможно, толкование является лучшим термином. Исходный код для escape доступный по запросу (электронная почта к firstname отмечают точкой lastname в точке Gmail com). Исходный код для al невероятно просто:

#include 
int main(int argc, char **argv)
{
    while (*++argv != 0)
        puts(*argv);
    return(0);
}

Это все. Это эквивалентно test.sh сценарий, который Robert Gamble показал и мог быть записан как функция оболочки (но функции оболочки не существовали в локальной версии Оболочки Bourne, когда я сначала записал al).

Также обратите внимание, что можно записать al как простой сценарий оболочки:

[ $# != 0 ] && printf "%s\n" "$@"

Условное выражение необходимо так, чтобы оно не производило вывода при передаче никакие аргументы. printf команда продолжит пустую линию только с аргументом строки формата, но программа C ничего не производит.

100
задан Christopher Rapcewicz 9 December 2013 в 18:46
поделиться

7 ответов

Несколько таблиц помогают в следующих случаях / случаях:

(a) если разные люди будут разрабатывать приложения задействуя разные таблицы, имеет смысл разделить их.

(b) Если вы хотите предоставить разным людям разные полномочия для разных частей сбора данных, может быть удобнее разделить их. (Конечно, вы можете определить представления и соответствующим образом разрешить их.)

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

(d) Меньший размер следа может быть удобен при разработке приложений для сбора конкретных данных одного объекта.

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

Я бы проголосовал за несколько таблиц - с соответствующим образом разделенными данными.

Удачи.

62
ответ дан 24 November 2019 в 04:54
поделиться

Объединение таблиц называется денормализацией.

Это может (или не может) помочь сделать некоторые запросы (которые заставляют много JOIN s) работать быстрее. расходы на создание ада обслуживания.

MySQL может использовать только метод JOIN , а именно NESTED LOOPS .

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

Поиск записи - довольно дорогостоящая операция, которая может занять в десятки раз больше времени, чем сканирование чистой записи.

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

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

С другой стороны, адское обслуживание гарантировано.

35
ответ дан 24 November 2019 в 04:54
поделиться

Имеют ли все из этих таблиц отношение 1-к-1 ? Например, будет ли каждая пользовательская строка иметь только одну соответствующую строку в user_stats или user_levels ? Если так, возможно, имеет смысл объединить их в одну таблицу. Если отношение не 1 к 1 , вероятно, не имеет смысла объединять (денормализовать) их.

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

ETA:

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

Если вы посмотрите на то, как вы используете данные, я предполагаю, что вы обнаружите, что примерно 80% ваших запросов используют 20% этих данных, а остальные 80% данных используются лишь изредка. Объедините эти часто используемые 20% в одну таблицу и оставьте 80%, которые вы не часто используете, в отдельных таблицах, и вы, вероятно, получите хороший компромисс.

Вы обнаружите, что примерно 80% ваших запросов используют 20% этих данных, а остальные 80% данных используются лишь иногда. Объедините эти часто используемые 20% в одну таблицу и оставьте 80%, которые вы не часто используете, в отдельных таблицах, и вы, вероятно, получите хороший компромисс.

Вы обнаружите, что примерно 80% ваших запросов используют 20% этих данных, а остальные 80% данных используются лишь иногда. Объедините эти часто используемые 20% в одну таблицу и оставьте 80%, которые вы не часто используете, в отдельных таблицах, и вы, вероятно, получите хороший компромисс.

14
ответ дан 24 November 2019 в 04:54
поделиться

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

вы можете начать переосмысливать этот подход.

вы можете начать переосмысливать этот подход.

3
ответ дан 24 November 2019 в 04:54
поделиться

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

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

Мне кажется, что вы можете пропустить User_Details, поскольку это, вероятно, отношение 1 к 1 с пользователями. Но в остальном, вероятно, много строк на пользователя?

1
ответ дан 24 November 2019 в 04:54
поделиться

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

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

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

17
ответ дан 24 November 2019 в 04:54
поделиться

Создание одной массивной таблицы противоречит принципам реляционной базы данных. Я бы не стал объединять их все в одну таблицу. Вы собираетесь получить несколько экземпляров повторяющихся данных. Например, если у вашего пользователя три интереса, у вас будет 3 строки с одними и теми же данными пользователя, чтобы сохранить три разных интереса. Определенно используйте подход с несколькими «нормализованными» таблицами. См. эту страницу Wiki для нормализации базы данных.

Изменить: Я обновил свой ответ, так как вы обновили свой вопрос ... Я даже больше согласен с моим первоначальным ответом, поскольку ...

большая часть этих ячеек является вероятно, останется пустым

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

Я работал в телефонной компании, где было множество таблиц, получение данных может потребовать множества присоединяется. Когда производительность чтения из этих таблиц была критической, тогда создавались процедуры, которые могли генерировать плоскую таблицу (т.е. денормализованную таблицу), которая не требовала объединений, вычислений и т.д., на которые могли бы указывать отчеты. Затем они использовались вместе с агентом сервера SQL для выполнения задания через определенные промежутки времени (т.е. еженедельный просмотр некоторой статистики будет запускаться один раз в неделю и так далее).

9
ответ дан 24 November 2019 в 04:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: