Использование с 2 подзапросами вместе с UNION ALL
и NOT IN
должно работать для вас. Первый запрос выберет 40 строк, упорядоченных по ranking
, второй запрос с подзапросом выберет все остальные строки , кроме первые 40 строк, которые уже выбраны первым подзапросом, и упорядочит его по score
. Предложение UNION ALL объединит эти 2 записи подзапроса в один набор. Надеюсь, что это помогает и понятно :) сейчас.
SELECT * FROM tbl_featured_professional ORDER BY ranking LIMIT 40
UNION ALL
SELECT * FROM tbl_featured_professional WHERE id NOT IN (SELECT * FROM tbl_featured_professional ORDER BY ranking LIMIT 40)
ORDER BY score
Существует дополнительное, не упомянутое условие, чтобы EFLAGS.AC действительно вступил в силу. CR0.AM должен быть установлен, чтобы предотвратить отключение INT 17h в старых операционных системах, предшествующих 486, которые не имеют обработчика для этого исключения. К сожалению, Windows не устанавливает его по умолчанию, вам нужно написать драйвер режима ядра, чтобы установить его.
символ *нечто, вероятно, выровненный к международным границам. Попробуйте это:
int bar = *(int *)(foo + 1);
Ситуации являются редкими, где невыровненный доступ вызовет проблемы на x86 (вне наличия доступа к памяти, занимают больше времени). Вот некоторые из тех, я услышал о:
Вы не могли бы считать это как x86 проблема, но операционное преимущество SSE от выравнивания. Выровненные данные могут использоваться в качестве исходного операнда памяти для сохранения инструкций. Инструкции невыравнивать-загрузки как movups
медленнее, чем movaps
на микроархитектуре перед Nehalem, но на Nehalem и позже (и семейство Бульдозера AMD), невыровненные 16-байтовые загрузки/хранилища почти так же эффективны как невыровненные 8-байтовые загрузки/хранилища; единственный uop и никакой штраф вообще, если данные, оказывается, выровненные во времени выполнения или не пересекают границу строки кэша, в других отношениях эффективную поддержку оборудования для разделений строки кэша. Разделения 4k являются очень дорогими (~100 циклов) до Skylake (вниз к ~10 циклам как разделение строки кэша). См. https://agner.org/optimize / и ссылки производительности в wiki тега x86 для большего количества информации
, взаимно блокируемые операции (как lock add [mem], eax
) очень медленные, если они не достаточно выровненные, особенно если они пересекают границу строки кэша, таким образом, они не могут только использовать блокировку кэша в ядре процессора. В более старых (ошибочных) системах SMP они могли бы на самом деле сбой, чтобы быть атомарными (см. https://blogs.msdn.com/oldnewthing/archive/2004/08/30/222631.aspx).
и другая возможность, обсужденная Raymond Chen, при контакте с устройствами, которые имеют окруженную валом память аппаратных средств (по общему признанию чудная ситуация) - https://blogs.msdn.com/oldnewthing/archive/2004/08/27/221486.aspx
, который я вспоминаю (но не имейте ссылки для - таким образом, я не уверен в этом), подобные проблемы с невыровненными доступами, которые колеблются между границами страницы, которые также включают отсутствие страницы. Я буду видеть, могу ли я вскопать ссылку для этого.
И я изучил что-то новое при изучении этого вопроса (я задавался вопросом о" $ps |= (1<<18)
" команда GDB, которая была упомянута в паре мест). Я не понял, что x86 центральные процессоры (запускающийся с 486, которыми это кажется) имеют способность вызвать исключение, когда неправильно выровненный доступ выполняется.
От "Программирования Jeffery Richter Приложений для Windows, 4-й Ed":
Позволяют нам более тщательно изучить то, как x86 ЦП обрабатывает выравнивание данных. x86 ЦП содержит специальный битовый флаг в своем регистре EFLAGS, названном AC (проверка выравнивания) флаг. По умолчанию этот флаг обнуляется, когда ЦП сначала получает питание. Когда этот флаг является нулем, ЦП автоматически делает то, что он имеет к тому, для успешного доступа к неправильно выровненным значениям данных. Однако, если этот флаг установлен на 1, ЦП выпускает INT 17-е прерывание каждый раз, когда существует попытка получить доступ к неправильно выровненным данным. x86 версия Windows 2000 и Windows 98 никогда не изменяет этот флаговый бит ЦП. Поэтому Вы никогда не будете видеть, что исключение неточного совмещения данных происходит в приложении, когда оно будет работать на x86 процессоре.
Это было новостями мне.
, Конечно, большая проблема с неправильно выровненными доступами состоит в том, что, когда Вы в конечном счете идете для компиляции кода для non-x86/x64 процессор, Вы заканчиваете тем, что имели необходимость разыскать и зафиксировать целый набор материала, так как фактически все другие 32-разрядные или более крупные процессоры чувствительны к проблемам выравнивания.
char *foo = "....";
foo++;
int *bar = (int *)foo;
компилятор поместил бы нечто на границу слова, и затем при постепенном увеличении его, это в word+1, который недопустим для международного указателя.
#include <stdio.h>
int main(int argc, char **argv)
{
char c[] = "a";
printf("%d\n", *(int*)(c));
}
Это дает мне SIGBUS после установки set $ps |= (1<<18)
в gdb, который, по-видимому, брошен, когда выравнивание адреса неправильное (среди других причин).
Править: Довольно легко повысить SIGBUS:
int main(int argc, char **argv)
{
/* EDIT: enable AC check */
asm("pushf; "
"orl $(1<<18), (%esp); "
"popf;");
char c[] = "1234567";
char d[] = "12345678";
return 0;
}
Рассмотрение дизассемблирования основного в gdb:
Dump of assembler code for function main:
....
0x08048406 <main+34>: mov 0x8048510,%eax
0x0804840b <main+39>: mov 0x8048514,%edx
0x08048411 <main+45>: mov %eax,-0x10(%ebp)
0x08048414 <main+48>: mov %edx,-0xc(%ebp)
0x08048417 <main+51>: movl $0x34333231,-0x19(%ebp) <== BAM! SIGBUS
0x0804841e <main+58>: movl $0x38373635,-0x15(%ebp)
0x08048425 <main+65>: movb $0x0,-0x11(%ebp)
Во всяком случае, Christoph, которого Ваша тестовая программа приводит к сбою в соответствии с Linux, повышающим SIGBUS, как это должно. Это - вероятно, вещь Windows?
Можно включить Контрольный бит Выравнивания в коде с помощью этого отрывка:
/* enable AC check */
asm("pushf; "
"orl $(1<<18), (%esp); "
"popf;");
Кроме того, удостоверьтесь, что флаг был действительно установлен:
unsigned int flags;
asm("pushf; "
"movl (%%esp), %0; "
"popf; " : "=r"(flags));
fprintf(stderr, "%d\n", flags & (1<<18));