#php #sql #laravel
#php #sql #laravel
Вопрос:
Я попытался объединить 2 запроса в 1, используя объединения
// Query 1
$entity = DB::select("
SELECT memo_id
FROM entities
WHERE entity_type = 4
AND entity_id = '".$entity_nr."'
LIMIT 1
");
$memo = DB::select("
SELECT memo
FROM memos
WHERE id = '".$entity[0]->memo_id."'
LIMIT 1
");
// Query 2
$memo = DB::select('
SELECT memo
FROM memos
JOIN entities ON "memos"."id" = "entities"."memo_id"
WHERE "entities"."entity_type" = 4
AND "entities"."entity_id" IN (?)
LIMIT 1
', [$entity_nr]);
2 запроса Query 1
выполняются менее чем за секунду. Query 2
занимает несколько секунд. Если я удалю предложение where Query 2
, оно выполняется быстро. Использование AND "entities"."entity_id" = ?
также не помогло.
Как это решить?
ОБНОВЛЕНИЕ 2020-09-27
Рефакторинг моего вопроса. Надеюсь, это прояснит ситуацию. Ожидаемый результат — получить памятку. Всегда есть только 1 возможное совпадение. В примере кода я не проверяю наличие результата, потому что на самом деле это ничего не добавляет к вопросу.
База данных, которую я использую, — это «Actian Zen database».
Структура таблицы
//////////////////////////
// Table: "entity_memo" //
//////////////////////////
CREATE TABLE "entity_memo" (
"entity_type" SMALLINT,
"entity_id" CHAR(15),
"memo_id" INTEGER
);
CREATE UNIQUE INDEX "key0" ON "entity_memo" ( "entity_type", "entity_id", "memo_id" );
CREATE INDEX "key1" ON "entity_memo" ( "memo_id", "entity_type", "entity_id" );
//////////////////////////
// Table: "memos" //
//////////////////////////
CREATE TABLE "memos" (
"id" INTEGER,
"memo" LVAR(32002)
);
CREATE UNIQUE INDEX "key0" ON "memos" ( "id" );
Вариант 1 (= быстрый, но 2 запроса)
$entity_type = 1;
$entity_id = 'ABC123456';
$entity = DB::select('
SELECT memo_id
FROM entity_memo
WHERE entity_type = ?
AND entity_id = ?
LIMIT 1
', [$entity_type, $entity_id]
);
$memo = DB::select('
SELECT memo
FROM memos
WHERE id = ?
LIMIT 1
', [$entity[0]->memo_id]
);
return $memo[0]->memo;
Вариант 2 (= медленный, но только 1 запрос)
$entity_type = 1;
$entity_id = 'ABC123456';
$memo = DB::select('
SELECT memo
FROM memos
JOIN entity_memo ON "memos"."id" = "entity_memo"."memo_id"
WHERE "entity_memo"."entity_type" = ?
AND "entity_memo"."entity_id" = ?
LIMIT 1
', [$entity_type, $entity_id]
);
return $memo[0]->memo;
Комментарии:
1. Я, честно говоря, не понимаю, как этот запрос вообще может работать, поскольку вы используете неправильные кавычки вокруг имен таблиц и столбцов. В MySQL значения заключаются в двойные кавычки. Для кодирования имен таблиц и столбцов (что необходимо только в том случае, если эти имена конфликтуют с зарезервированными ключевыми словами в MySQL), вам нужно использовать обратные тики. Или есть какая-то «магия Laravel», которая исправляет это для вас?
2. Кстати, почему вы используете
IN
вместо=
в последнем запросе?3. @Magnus Eriksson Потому что я прочитал статью, что это, возможно, ускорит запрос
4. @Magnus Eriksson tbh, я использую не MySQL, а довольно неизвестный тип БД (я не контролирую структуру БД), но я могу перевести соответствующие ответы на свои нужды 🙂
5. Поскольку это не MySQL, я удалил этот тег. Важно, чтобы мы знали, какую базу данных вы используете, иначе мы вообще не сможем помочь с какими-либо деталями, которые, скорее всего, понадобятся в этом вопросе.
Ответ №1:
Это будет выглядеть проще, если вы напишете его без объединений.
SELECT ent.unique_id, mem.memo
FROM entities ent, memos mem
WHERE ent.unique_id = mem.unique_id
AND ent.entity_type = 4
AND ent.entity_id = '".$entity_nr."'
Но причина медленной работы запроса кроется в самих таблицах. Вы должны добавить индексы к столбцам PK и FK, чтобы запрос работал быстрее.
Комментарии:
1. 1. Не добавляйте значения в свой запрос вручную таким образом. 2. Использование JOIN — это правильный способ ОБЪЕДИНЕНИЯ таблиц.
2. Значения безопасны, хотя они создаются программно
3. Как это не ОБЪЕДИНЕНИЕ? Похоже, он просто использует старый синтаксис.