@synapse_people

Как правильно хранить таблицы для быстродействия?

Есть 4 таблицы, в ней 256 значений в каждой.
Структура простая - idx TINYINT UNSGINED NOT NULL, value TINYINT UNSGINED NOT NULL;
При запросе требуется выбрать 16 значений по случайным индексам (WHERE idx=....), случайными не имеется ввиду случаные строки ORDER BY RAND(), а то, что будет выбрано значение, которое зависит от другого значения.
Такая операция повторяется 2 млн раз и занимает 46 секунд. Аналогичный код в PHP работает 15 секунд. В c/c++ - менее 0.1 сек. Необходимо реализовать структуру таким образом, чтобы все запросы выполнялсь со скоростью с.
Вот пример запроса:
SELECT
        (TT1_t0^TT2_t5 ^TT3_t10^TT4_t15^u32_k0)&0xffffffff `i0`,
(TT4_t3^TT1_t4 ^TT2_t9 ^TT3_t14^u32_k1)&0xffffffff `i1`,
(TT3_t2^TT4_t7 ^TT1_t8 ^TT2_t13^u32_k2)&0xffffffff `i2`,
(TT2_t1^ TT3_t6^TT4_t11^TT1_t12^u32_k3)&0xffffffff `i3`
FROM (
SELECT
        TT1_t0.value TT1_t0, TT2_t5.value TT2_t5, TT3_t10.value TT3_t10, TT4_t15.value TT4_t15,
        TT4_t3.value TT4_t3, TT1_t4.value TT1_t4, TT2_t9.value TT2_t9,   TT3_t14.value TT3_t14,
        TT3_t2.value TT3_t2, TT4_t7.value TT4_t7, TT1_t8.value TT1_t8,   TT2_t13.value TT2_t13,
        TT2_t1.value TT2_t1, TT3_t6.value TT3_t6, TT4_t11.value TT4_t11, TT1_t12.value TT1_t12,
        
        ((k0.value|(k1.value<<8)|(k2.value<<16)|(k3.value<<24))&0xffffffff) u32_k0,
        ((k4.value|(k5.value<<8)|(k6.value<<16)|(k7.value<<24))&0xffffffff) u32_k1,
        ((k8.value|(k9.value<<8)|(k10.value<<16)|(k11.value<<24))&0xffffffff) u32_k2,
        ((k12.value|(k13.value<<8)|(k14.value<<16)|(k15.value<<24))&0xffffffff) u32_k3

        FROM (select 1) fake

          JOIN `text` `t0`  ON `t0`.`idx`=(:off1+0)
          JOIN `text` `t1`  ON `t1`.`idx`=(:off1+1)
          JOIN `text` `t2`  ON `t2`.`idx`=(:off1+2)
          JOIN `text` `t3`  ON `t3`.`idx`=(:off1+3)
          JOIN `text` `t4`  ON `t4`.`idx`=(:off1+4)
          JOIN `text` `t5`  ON `t5`.`idx`=(:off1+5)
          JOIN `text` `t6`  ON `t6`.`idx`=(:off1+6)
          JOIN `text` `t7`  ON `t7`.`idx`=(:off1+7)
          JOIN `text` `t8`  ON `t8`.`idx`=(:off1+8)
          JOIN `text` `t9`  ON `t9`.`idx`=(:off1+9)
          JOIN `text` `t10` ON `t10`.`idx`=(:off1+10)
          JOIN `text` `t11` ON `t11`.`idx`=(:off1+11)
          JOIN `text` `t12` ON `t12`.`idx`=(:off1+12)
          JOIN `text` `t13` ON `t13`.`idx`=(:off1+13)
          JOIN `text` `t14` ON `t14`.`idx`=(:off1+14)
          JOIN `text` `t15` ON `t15`.`idx`=(:off1+15)

          JOIN `exp_data` `k0` ON `k0`.`idx`=(:off2+0)
          JOIN `exp_data` `k1` ON `k1`.`idx`=(:off2+1)
          JOIN `exp_data` `k2` ON `k2`.`idx`=(:off2+2)
          JOIN `exp_data` `k3` ON `k3`.`idx`=(:off2+3)
          JOIN `exp_data` `k4` ON `k4`.`idx`=(:off2+4)
          JOIN `exp_data` `k5` ON `k5`.`idx`=(:off2+5)
          JOIN `exp_data` `k6` ON `k6`.`idx`=(:off2+6)
          JOIN `exp_data` `k7` ON `k7`.`idx`=(:off2+7)
          JOIN `exp_data` `k8` ON `k8`.`idx`=(:off2+8)
          JOIN `exp_data` `k9` ON `k9`.`idx`=(:off2+9)
          JOIN `exp_data` `k10` ON `k10`.`idx`=(:off2+10)
          JOIN `exp_data` `k11` ON `k11`.`idx`=(:off2+11)
          JOIN `exp_data` `k12` ON `k12`.`idx`=(:off2+12)
          JOIN `exp_data` `k13` ON `k13`.`idx`=(:off2+13)
          JOIN `exp_data` `k14` ON `k14`.`idx`=(:off2+14)
          JOIN `exp_data` `k15` ON `k15`.`idx`=(:off2+15)

          JOIN `TT1` `TT1_t0` ON `TT1_t0`.`idx`=`t0`.`value`
          JOIN `TT2` `TT2_t5` ON `TT2_t5`.`idx`=`t5`.`value`
          JOIN `TT3` `TT3_t10` ON `TT3_t10`.`idx`=`t10`.`value`
          JOIN `TT4` `TT4_t15` ON `TT4_t15`.`idx`=`t15`.`value`
        
          JOIN `TT4` `TT4_t3` ON `TT4_t3`.`idx`=`t3`.`value`
          JOIN `TT1` `TT1_t4` ON `TT1_t4`.`idx`=`t4`.`value`
          JOIN `TT2` `TT2_t9` ON `TT2_t9`.`idx`=`t9`.`value`
          JOIN `TT3` `TT3_t14` ON `TT3_t14`.`idx`=`t14`.`value`
        
          JOIN `TT3` `TT3_t2` ON `TT3_t2`.`idx`=`t2`.`value`
          JOIN `TT4` `TT4_t7` ON `TT4_t7`.`idx`=`t7`.`value`
          JOIN `TT1` `TT1_t8` ON `TT1_t8`.`idx`=`t8`.`value`
          JOIN `TT2` `TT2_t13` ON `TT2_t13`.`idx`=`t13`.`value`

          JOIN `TT2` `TT2_t1` ON `TT2_t1`.`idx`=`t1`.`value`
          JOIN `TT3` `TT3_t6` ON `TT3_t6`.`idx`=`t6`.`value`
          JOIN `TT4` `TT4_t11` ON `TT4_t11`.`idx`=`t11`.`value`
          JOIN `TT1` `TT1_t12` ON `TT1_t12`.`idx`=`t12`.`value`
        ) :tblalias

У кого есть какие идеи? П.с. индекс на idx - PK во всех таблицах.
В с таблицы обьявлены как uint8_t TT1[256] = {....};
а text и exp_data - как указатели на uint8_t, по сути является массивом из uint8, text - 128 элементов, exp_data = 200 элементов.
Я пробовал заменять JOIN на WHERE, особого прироста скорости не дало. Также пробовал сделать несколько колонок в text, t0,t1,t2,t4, чтобы получать данные для итерации сразу, а не джойнить с ними при каждом запросе-на скорость не повлияло. Пробовал запихивать в процедуру, также не дает эффекта.
Мне кажется необходимо разместить таблицы TT1-TT4, а также text, exp_data другим образом, чтобы они были как массивы в с. Но я не знаю как такое сделать в SQL.
В целом конструкция запроса такая UPDATE ..... SELECT .... .
P.s. вызывается подготовленными запросами, в каждом запросе подготовленно 8 таких SELECT через UNION. Все таблицы располагаются в памяти (engine=MyISAM/MEMORY разницы не дают), если дописать TEMPORARY, то не дает дважды выбирать столбики из одной и той же таблицы.
Подойдут любые варианты, которые позволят добится производительности с.
Вот данные с профайлера для такого запроса:
https://pastebin.com/vtPMS0Np
Данные EXPLAIN:
https://pastebin.com/xCgWWJ3x
  • Вопрос задан
  • 173 просмотра
Пригласить эксперта
Ответы на вопрос 2
Melkij
@Melkij
PostgreSQL DBA
В c/c++ - менее 0.1 сек. Необходимо реализовать структуру таким образом, чтобы все запросы выполнялсь со скоростью с.

Адаптируйте свою реализацию алгоритма в UDF
https://dev.mysql.com/doc/refman/5.7/en/adding-udf.html
Ответ написан
saintbyte
@saintbyte
Django developer
Денормализация - для более простой выборки.
Денормализация и хранить данные в redis
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы