Медленный запрос с where в объединенном столбце

#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. Как это не ОБЪЕДИНЕНИЕ? Похоже, он просто использует старый синтаксис.