Новичок в sqlite пытается повысить производительность за счет проектирования баз данных, «присоединиться» и «где» - PullRequest
0 голосов
/ 06 августа 2011

У меня есть большая таблица (потенциально миллионы строк), которая в своей наивной форме будет содержать много повторений, например ::100100

CREATE TABLE sales(
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    salesperson TEXT,
    customer    TEXT
);

INSERT INTO sales VALUES(NULL, "Rod", "Acme");
INSERT INTO sales VALUES(NULL, "Jane", "Xyz Corp");
INSERT INTO sales VALUES(NULL, "Freddy", "Acme");
<... many more lines containing significant repetitions of each salesperson and each customer >

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

SELECT count(*) FROM sales WHERE salesperson="Jane";

Так что моя база данных должна быть переставлена ​​как:

CREATE TABLE sales(
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    salesperson INTEGER,
    customer    INTEGER
);

CREATE TABLE salespeople(
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    name        TEXT
);

CREATE TABLE customers(
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    name        TEXT
);

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

Я рассчитал тестирование глупого запроса по отношению к одной таблице v.s. СОЕДИНЕНИЕ с WHERE против версии с разделенными таблицами и «умной» версии примерно на 25% медленнее, поэтому ясно, что я что-то упускаю:

SELECT count(*) FROM sales INNER JOIN salespeople ON sales.salesperson=salespeople.id WHERE salespeople.name="Freddy";

Если я сначала посмотрю salesperson.id как отдельный запрос, я увижу время примерно на 33% быстрее, чем глупая реализация (что меньше, чем я ожидал).

SELECT id FROM salespeople WHERE name="Freddy";

... тогда

SELECT count(*) FROM sales WHERE salesperson=previouslyLookedUpId;

У меня складывается впечатление, что WHERE (в решении с несколькими таблицами) оценивается для каждой строки, а не один раз для определения соответствующего идентификатора продавца, как предполагалось. Очевидно, что мои запросы (или ограничения, или индексы?) Не позволяют эффективно работать с механизмом БД.

Я знаю только достаточно, чтобы знать, что не знаю достаточно ... Какой здесь правильный подход?

1 Ответ

1 голос
/ 06 августа 2011

Во-первых, см. Мой комментарий об индексах.

Во-вторых, целью "нормализации" структуры базы данных является не производительность.Часто бывает, что нормализованный дизайн будет работать медленнее, чем денормализованный или «сплющенный» стол.Объединения могут быть дорогими с точки зрения потребления ресурсов.

Цель нормализации - правильное представление сущностей и их отношений;если ваш домен точно сопоставлен с нормализованным дизайном, невозможно получить разные ответы на один и тот же вопрос.Это цель.

Кроме того, нормализованный дизайн является расширяемым.Это еще одно главное достоинство и цель.

Поскольку вы используете слово «умный».Нормализованный дизайн «простодушный», а не умный, хотя для достижения простоты нужны умы.

PS

Какую производительность вы получаете по сравнению со стандартным объединением, с этимподход:

                 from sales
                 where salespersonid = (select id from SALESPEOPLE where name = 'Joe')

когда SALESPEOPLE.name и salespersonid проиндексированы?

или это:

                ... from sales
                inner join
                (select id from SALESPEOPLE where name = 'Joe') as MYPEEPS
                on sales.salespersonid = MYPEEPS.id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...