Псевдонимы таблиц SQLite, влияющие на производительность запросов - PullRequest
2 голосов
/ 10 сентября 2011

Как SQLite внутренне обрабатывает псевдоним?

Создает ли псевдоним имени таблицы внутри себя копию той же таблицы или она просто ссылается на ту же таблицу, не создавая копию?

Когда я создаю в своем коде несколько псевдонимов одной и той же таблицы, производительность запроса сильно падает!

В моем случае у меня есть одна таблица, назовите ее MainTable, а именно 2 столбца, имя и значение. Я хочу выбрать несколько значений в одной строке как разные столбцы. например

Имя: а, б, в, г, д, е
Значение: p, q, r, s, t, u
такой, что а соответствует р и т. д.

Я хочу выбрать значения для имен a, b, c и d в одной строке => p, q, r, s Поэтому я пишу запрос

SELECT t1.name, t2.name, t3.name, t4.name  
FROM MainTable t1, MainTable t2, MainTable t3, MainTable t4
WHERE t1.name = 'a' and t2.name = 'b' and t3.name = 'c' and t4.name = 'd';

Таким образом, написание запроса снижает производительность, когда размер таблицы увеличивается, как справедливо указано выше Ларри.

Есть ли эффективный способ получить этот результат. Я плохо разбираюсь в SQL-запросах :(

Ответы [ 3 ]

2 голосов
/ 10 сентября 2011

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

 SELECT * FROM MyTable A, MyTable B;

если MyTable имеет 1000 записей, будет создан набор результатов с одним миллионом записей. Любые другие критерии выбора, которые вы включите, будут затем оцениваться по всем миллионам записей.

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

Обновлен ответ теперь, когда автор добавил запрос, который выполняется.

Тебе придется немного повозиться, чтобы получить желаемые результаты. Вам нужно использовать CASE и MAX, и, к сожалению, синтаксис для CASE немного многословен:

 SELECT MAX(CASE WHEN name='a' THEN value ELSE NULL END),
        MAX(CASE WHEN name='b' THEN value ELSE NULL END),
        MAX(CASE WHEN name='c' THEN value ELSE NULL END),
        MAX(CASE WHEN name='d' THEN value ELSE NULL END)
  FROM MainTable WHERE name IN ('a','b','c','d');

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

1 голос
/ 10 сентября 2011

Предположим, у вас есть таблица dbo.Customers с миллионом строк

SELECT * from dbo.Customers A

не приводит к созданию копии таблицы.

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

В обновленном тикете указано, что в одной строке должно быть 4 значения из разных запросов. Это довольно просто, при условии, что этот синтаксис действителен для sqllite

Вы можете видеть, что следующие четыре запроса при выполнении в последовательном режиме дают желаемое значение, но в 4 строках.

SELECT t1.name
FROM MainTable t1
WHERE t1.name='a';

SELECT t2.name
FROM MainTable t2
WHERE t2.name='b';

SELECT t3.name
FROM MainTable t3
WHERE t3.name='c';

SELECT t4.name
FROM MainTable t4
WHERE t4.name='d';

Хитрость заключается в том, чтобы просто запускать их как подзапросы, например, 5 запросов: 1 запрос драйвера, 4 подпрограммы выполняют всю работу. Этот шаблон будет работать только , если будет возвращена одна строка.

SELECT
(
    SELECT t1.name
    FROM MainTable t1
    WHERE t1.name='a'
) AS t1_name
,
(
    SELECT t2.name
    FROM MainTable t2
    WHERE t2.name='b'
) AS t2_name
,
(
    SELECT t3.name
    FROM MainTable t3
    WHERE t3.name='c'
) AS t3_name
, 
(
    SELECT t4.name
    FROM MainTable t4
    WHERE t4.name='d'
) AS t4_name
0 голосов
/ 10 сентября 2011

При псевдониме таблицы будет получена ссылка на исходную таблицу, существующую на протяжении всего оператора SQL.

...