LINUX.ORG.RU

mysql: SELECT FROM <вычисляемая таблица>


0

0

собственно как в MySQL выполнить SELECT из таблицы, имя которой заранее неизвестно и вычисляется в теле сохраняемой процедуры? что-то вроде:

CREATE PROCEDURE foo(IN param INT)
BEGIN
    DECLARE name CHAR(16);
    ...тут мы как-то вычисляем name на основании param...
    SELECT a, b FROM name;
END;

с одной стороны, кажется, что так сделать нельзя. с другой - оч хочется :) и оч не хочется писать толстый CASE на param в котором для каждого значения работаем с конкретной таблицей, бо значений может быть дюже много [сотни] и такой case будет жутко уродливый..

// wbr

Но вообще, непонятно нафига тогда в хранимую процедуру все запихивать. Они же медленные, их нельзя дебажить, а использование таких prepare/execute скорее всего отрубает (итак небольшие) возможности какой-то внутрибазовой оптимизации, то есть преимуществ у хранимых процедур не остается никаких.

gods-little-toy ★★★
()
Ответ на: комментарий от gods-little-toy

> Но вообще, непонятно нафига тогда в хранимую процедуру все запихивать.

о бизнес-логике когда-нибудь слышали ?

kto_tama ★★★★★
()
Ответ на: комментарий от gods-little-toy

> PREPARE stmt FROM 'text'; EXECUTE stmt;

да, про prepared statements я что то и не подумал. такой подход вполне работает, спасибо :) вопрос снят.

// wbr

klalafuda ★☆☆
() автор топика
Ответ на: комментарий от kto_tama

> о бизнес-логике когда-нибудь слышали ?

<троллинг> в бизнесе нет логики :-) </троллинг>

gods-little-toy ★★★
()
Ответ на: комментарий от gods-little-toy

> Но вообще, непонятно нафига тогда в хранимую процедуру все запихивать.

для любопытствующих поясню, откуда взялся такой вопрос.

допустим, у нас есть следующая таблица:

[code]
CREATE TABLE foo (
id SERIAL,
a INT,
b INT,
PRIMARY KEY (id)
);
[/code]

таблица у нас ооочень большая, сотни тысяч/миллионы/сколько хотите записей, и к ней постоянно идёт плотный поток разнообразных SELECT, INSERT, UPDATE, DELETE из кучи параллельных соединений. причём доступ идёт исключительно по ключу id. такая вот популярная таблица.

хочешь не хочешь, но рано или поздно всё становится раком. а хочется, чтобы оно раком не вставало.

одно из решений в лоб - это разбить таблицу foo на N аналогичных таблиц с заданным именем, скажем fooXXX, где номер таблицы XXX как-то зависит от id. если id равномерно распределяется, то XXX вполне может быть модулем id по N.

[code]
CREATE TABLE foo (...);
CREATE TABLE foo0 LINE foo;
CREATE TABLE foo1 LINE foo;
....
CREATE TABLE foo<N-1> LINE foo;
[/code]

собственно разбиение на 10 таблиц уже даёт ощутимый прирост почти на порядок, а разбиение же на 100 таблиц как правило зло и дёшево решает все проблемы с нагрузкой.

но параллельно возникают уже другие проблемы как то: невозможность работы с foo как целым. для заданного id приходится каждый раз искать его таблицу и работать уже с ней. в принципе, когда это делается из кода, выбор названия таблицы по id - это не проблема. хотя и тут можно допустить очепятку. а вот когда нужно что-то делать руками, то становится уже жутко неудобно.

вполне логично желание обернуть популярные операции доступа к foo набором сохранённых процедур, которые бы внутри скрывали все детали общения с foo. разбита она, не разбита, как именно разбита, как мы вычисляем XXX по id - это уже не наше дело но внутренней логики базы.

вот собственно и весь use case.

btw AFAIR pgsql умеет делать такой сплит таблицы с заданием хеш функции от ключа собственными внутренними средствами. и с точки зрения юзера есть единая foo, которая на самом деле внутри примерно так же разбита. впрочем, сам я этим никогда не пользовался. к сожалению, ничего подобного в MySQL я не встречал. по крайней мере в 5.0.XX.

// wbr

klalafuda ★☆☆
() автор топика
Ответ на: комментарий от klalafuda

В MySQL давно есть такая штука, как MERGE таблицы: http://dev.mysql.com/doc/refman/5.1/en/merge-storage-engine.html Разбивай таблицу как хочешь, а надо работать как с единым целым - обращайся к MERGE. Очень хорошо для протоколов, например.

crimaniak
()
Ответ на: комментарий от crimaniak

> В MySQL давно есть такая штука, как MERGE таблицы: http://dev.mysql.com/doc/refman/5.1/en/merge-storage-engine.html Разбивай таблицу как хочешь, а надо работать как с единым целым - обращайся к MERGE. Очень хорошо для протоколов, например.

все бы хорошо, но AFAIU они не умеют работать с memory таблицами, только с MyISAM. что, к сожалению, неприемлемо бо трафик на столько плотный, что что-либо, отличное от memory, просто умирает. что myisam что innodb.

// wbr

klalafuda ★☆☆
() автор топика
Ответ на: комментарий от true_admin

> тогда уж table partitioning

бегло просмотрел 5.0. reference manual и не нашел такого. если не секрет, что это и с чем это едят?

// wbr

klalafuda ★☆☆
() автор топика
Ответ на: комментарий от klalafuda

Оно тока в 5.1 :(

Вот первые ссылки из гугля. Я не смотрел что там, но, судя по урлам, там что-то интересное. Если в реальной системе такое потестишь то напиши плиз чем закончилось.

http://dev.mysql.com/doc/refman/5.1/en/partitioning.html

http://blog.thinkphp.de/archives/353-Is-MySQL-partitioning-useful-for-very-bi...

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

> Оно тока в 5.1 :(

так получилось, что слышал и не раз, что 5.1 ещё заметно сыроват для production. на том же opennet AFAIR. впрочем, не могу ни подтвердить ни опровергнуть это утверждение. по крайней мере собственным опытом.

// wbr

klalafuda ★☆☆
() автор топика
Ответ на: комментарий от klalafuda

Да, он сырой. Впрочес, 5.0 тоже не подарок, видел как простой join повисал на 5.0.77 если его запустить когда по таблице уже шуршат другие запросы. Пришлось городить велосипед чтобы одновременно с таблицей работало не более одного процесса.

true_admin ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.