Autor wpisu: Vokiel, dodany: 21.09.2010 00:41, tagi: mysql
Pisząc różnego rodzaju aplikacje zdarza się, że trzeba wprowadzić pewną losowość. Jeśli aplikacja jest oparta na bazie danych, taką losowość najłatwiej wprowadzić pobierając losowe dane. Przerabiając ostatnio stary system, oparty jeszcze o pliki tekstowe postanowiłem przenieść go na bazę danych MySQL. Ponieważ duża część systemu z założenia ma być losowa, zatem koniecznym było napisanie dobrej funkcji wybierającej losowe dane z bazy danych. Wydaje się to banalnie proste, jednak nie tak bardzo.
Najczęstsze rozwiązanie
Posłużę się prawdziwym przykładem, nad którym pracowałem. Mamy tabelę keys
, która, dla uproszczenia zawiera 2 kolumny: id | key
. Chcemy pobrać jeden losowy rekord. Pierwsza myśl przy próbie napisania takiego zapytania to:
SELECT `id`,`key` FROM `keys`ORDER BY RAND() LIMIT 1;
Szukając rozwiązania w necie najczęściej natkniemy się właśnie na takie rozwiązanie. Nawet przy niewielkiej ilości rekordów nie nazwałbym tego rozwiązania akceptowalnym. Oto co się dzieje przy niewielkiej ilości rekordów:
mysql> SELECT COUNT(`id`) as ILOSC FROM `keys`; +--------+ | ILOSC | +--------+ | 113528 | +--------+ 1 row in set (0.09 sec) mysql> SELECT `id`,`key` FROM `keys` ORDER BY RAND() LIMIT 1; +--------+-------+ | id | key | +--------+-------+ | 143941 | yahoo +--------+-------+ 1 row in set (0.61 sec) mysql> DESCRIBE SELECT `id`,`key` FROM `keys` ORDER BY RAND() LIMIT 1; +----+-------------+-------+------+---------------+------+---------+------+--------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+--------+---------------------------------+ | 1 | SIMPLE | keys | ALL | NULL | NULL | NULL | NULL | 113739 | Using temporary; Using filesort | +----+-------------+-------+------+---------------+------+---------+------+--------+---------------------------------+ 1 row in set (0.04 sec)
Więcej niż pół sekundy! Ledwo ponad 100 000 rekordów, a zapytanie trwa 0,6 sekundy. Takie rozwiązanie w żadnym wypadku nie może zostać.
Inne rozwiązania
Aby nie wymyślać koła na nowo przeszukałem czeluście Wujka G. Okazało się, że powyższe rozwiązanie jest najczęściej występującym, niemalże jedynym. Kolejne rozwiązania opierają się już na wykorzystaniu PHP i pobieraniu rekordów poprzez zastosowanie kilku zapytań. Przykładowe rozwiązanie:
$range_result = mysql_query(" SELECT MAX(`id`) AS max_id , MIN(`id`) AS min_id FROM `table` "); $range_row = mysql_fetch_object( $range_result ); $random = mt_rand( $range_row->min_id , $range_row->max_id ); $result = mysql_query(" SELECT * FROM `table` WHERE `id` >= $random LIMIT 0,1 ");
Pobranie tylko jednego losowego rekordu i aż 2 zapytania? Wydaje się, że powinno dać się zrobić to sprawniej. Okazuje się, że autor powyższego kodu pokusił się o jego optymalizację, a nawet użycie pojedynczego zapytania sql.
SELECT `id`,`key` FROM `keys` WHERE id >= (SELECT FLOOR( MAX(`id`) * RAND()) FROM `keys` ) ORDER BY `id` LIMIT 1;
Zapytanie ma za zadanie pobrać rekord o id większym niż zaokrąglony w dół do liczby całkowitej wynik mnożenia maksymalnego id z wylosowaną liczbą z przedziału <0,1>
. Niby ma sens, ale co z „optymalnością” zapytania? Gorzej niż z pierwszym. Pomimo, że autor chwali zapytanie, że zajmuje 16% czasu pierwszego, mnie nie satysfakcjonuje. Wystarczy spojrzeć na wyniki działania:
mysql> SELECT `id`,`key` FROM `keys` WHERE id >= (SELECT FLOOR( MAX(`id`) * RAND()) FROM `keys` ) ORDER BY `id` LIMIT 1; +-----+-------------+ | id | key | +-----+-------------+ | 401 | alfa romeo +-----+-------------+ 1 row in set (12.64 sec) mysql> DESCRIBE SELECT `id`,`key` FROM `keys` WHERE id >= (SELECT FLOOR( MAX(`id`) * RAND()) FROM `keys` ) ORDER BY `id` LIMIT 1; +----+----------------------+-------+-------+---------------+------------------+---------+------+--------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+----------------------+-------+-------+---------------+------------------+---------+------+--------+-------------+ | 1 | PRIMARY | keys | index | NULL | PRIMARY | 4 | NULL | 1 | Using where | | 2 | UNCACHEABLE SUBQUERY | keys | index | NULL | UniqueSubdomains | 765 | NULL | 113715 | Using index | +----+----------------------+-------+-------+---------------+------------------+---------+------+--------+-------------+ 2 rows in set (0.04 sec)
Satysfakcjonujące rozwiązanie
Powyższe rozwiązanie po małej modyfikacji znacznie przyśpieszyło, na testowanej maszynie dało nie taki zły wynik (select z podaniem id wykonywany jest w 0.05s).
Autor wpisu: Kamil, dodany: 20.09.2010 19:08, tagi: framework, javascript
Autor wpisu: matipl, dodany: 20.09.2010 11:37, tagi: php
Coraz więcej mam do czynienia z cudzym kodem napisanym w PHP. Zauważyłem, że w wielu miejscach, nie wiem czy przez przypadek czy umyślnie, są tagi zamykające: ?> chociaż być nie powinny.
Tag zamykający powinniśmy używać wyłącznie w sytuacji, gdy poza PHP spodziewamy się czegoś innego, np. są to pliki widoku, w którym zagnieżdżamy wywołania, np.:
<h2><?php echo $page->name ?></h2> <php echo $page->content ?> <p>Tagi: <ul> <?php foreach($tags as $tag) : ??> <li><?php echo $tag->name ?></li> <?php endforeach ?> </ul> </p>
Dlaczego? Powód jest jeden: błędy. Za tagiem zamykającym może zakraść nam się spacja, znak nowej linii lub inne białe znaki. A to automatycznie powoduje błąd Cannot modify header information – headers already sent, jeśli w kolejnych plikach operujemy na nagłówku strony (header(), setcookie()).
Gdy nasz projekt jest duży, a ktoś zostawi ?> ze spacją lub innym cudem możemy mieć spory problem w szukaniu błędu i stracić sporo czasu. Poza tym interpreter nie musi zastanawiać się co i jak, gdzie kod PHP się zaczyna, a gdzie kończy.
Dlatego dla wszystkich plików, które zawierają tylko PHP zalecam niestosowanie tagu zamykającego ?>, który przez PHP jest niewymagany.
Polecam Wam również zaznajomienie się z Zend Framework Coding Standard.
Autor wpisu: batman, dodany: 16.09.2010 11:28, tagi: internet
Miejsce – Warszawa, klub 35mm, ostatnie piętro Multikina, Złote Tarasy. Czas – 15 września 2010 roku, kilka minut przed godziną 19. Na sali znajduje się 5 stołów oczekujących na przybycie kilkudziesięciu zaproszonych gości – przedstawicieli mediów, blogerów, deweloperów i innych osób zainteresowanych premierą najnowszej przeglądarki Mircosoftu. Sala została przygotowana w białych kolorach z niebieskimi akcentami, mającymi kolorystycznie nawiązywać do loga przeglądarki. Kilkanaście minut po 19, oglądamy w skupieniu przekaz na żywo z San Francisco, na którym prezentowany jest Internet Explorer 9. Po niecałej godzinie głos zabierają (już w Warszawie) przedstawiciele polskiego oddziału Microsoft.
Co nowego w wyglądzie?
Ponieważ przeglądarka skierowana jest przede wszystkim do masowego odbiorcy, Microsoft skupił się na zaprezentowaniu wodotrysków, pomijając kwestie stricte techniczne. Nie oznacza to, że Internet Explorer 9 ma się czego wstydzić. Po prostu statystyczny Kowalski nie jest zainteresowany technicznymi szczegółami. Dla niego najważniejsze jest, aby przeglądarka była jak najbardziej przyjazna w użytkowaniu, bezpieczna oraz szybka.
Od strony wizualnej oraz usability, Internet Explorer 9 może śmiało konkurować z pozostałymi przeglądarkami. Największą zmianą dotyczącą wyglądu jest umieszczenie zakładek (kart) obok paska adresu. Szerokość paska adresu można regulować, więc nie ma obawy, iż po otwarciu trzech kart, staną się one nieczytelne.
Kolejną rewolucją jest wykorzystanie dodatkowych możliwości jakie daje nowy interfejs Windows 7. Każdą z kart można przypiąć do paska zadań i korzystać z niej jak z osobnej aplikacji (pinned sites) – podobnie jak ma to miejsce w Google Chrome, z tą różnicą, że każdy ze skrótów oferuje dodatkowe opcje dostępne po kliknięciu na niego prawym przyciskiem myszy. Są to najczęściej wykonywane operacje w danym serwisie (Jump Lists). Dzięki takiemu rozwiązaniu, aplikacje internetowe sprawiają wrażenie zainstalowanych w systemie. W przypadku Facebooka mamy do dyspozycji następującą Jump Listę.
W chwili obecnej funkcjonalność taką oferują Facebook, LinkedIn, czy IMDB.
Co więcej, aplikacje internetowe mogą przy pomocy HTML5 urozmaicić swój wygląd poprzez dodanie efektów opartych o nowy standard. Na taki krok zdecydowała się wyszukiwarka Bing, która będzie dostarczać interaktywne tła.
Autor wpisu: matipl, dodany: 14.09.2010 15:32, tagi: php
Kto sądzi z Was, że takiego tworu jak Delphi nie ma już na rynku bardzo się myli. Z języka Delphi nadal się korzysta. W 2009 roku Delphi był na 11. pozycji w najpopularniejszych językach programowania, a na dodatek środowiska programistyczne dla Delphi wciąż się rozwijają.
Firma Embarcadero, która w 2008 roku kupiła pakiet CodeGear od firmy Borland wydała właśnie nowe środowisko RAD m.in. dla języka Delphi – RAD Studio XE.
RAD Studio XE oprócz środowisk Delphi XE i C++ Builder XE zawiera także nowe środowisko IDE dla PHP – RadPHP™XE oraz nową wersję Delphi Prism™ XE, do programowania .NET oraz Mono. A oto nowości w RAD Studio:
- SVN
- W pełni zintegrowane IDE do zespołowego zarządzania kodem źródłowym
- FinalBuilder Embarcadero Edition
- Audyty, metryki, formatowanie i generowanie dokumentacji bezpośrednio z linii wiersza poleceń. Automatyzacja procesu tworzenia buildów
- AQTime Standard
- Narzędzie do optymalizowania wydajności aplikacji
- Beyond Compare Text Compare
- Rozszerzenia w edytorze kodu: wyszukiwanie, formatowanie i nawigowanie po kodzie
- CodeSite Express
- Tworzenie wysokiej jakości aplikacji z logowaniem i rozbudowanymi opcjami debugowania
Dodatkowo nowe środowisko posiada nowe komponenty dla Microsoft Windows Azure data types, łatwiejsze wdrażanie „w chmurze” na Amazon EC2 oraz nowe właściwości DataSnap do tworzenia aplikacji wielowarstwowych.
Z okazji premiery nowego środowiska dla Delphi zaplanowano również 3-godzinne konferencje w 5 miastach Polski:
DATA KONFERENCJI | MIASTO | HOTEL |
15 września 2010 | Warszawa | Gromada Centrum |
21 września 2010 | Poznań | Novotel Malta |
22 września 2010 | Gdańsk | Novotel Marina |
28 września 2010 | Wrocław | Mercure Panorama |
29 września 2010 | Kraków | Orbis Cracovia |
Jak widać po coraz większym wsparciu konkurencyjnych języków/rozwiązań firma Embarcadero zdaje sobie sprawę, że lata świetności Delphi ma za sobą. Od siebie dodam, że Delphi bardzo dobrze spełnia swoją rolę jako gruby klient. Nadal szybko tworzy/rozwija się w nim aplikacje i posiada integrację z przeróżnymi stworami (np. FirebirdSQL) przez co nie ma dużego „ciśnienia” aby już działające aplikacje korporacyjne zmieniać na inne technologie.
Autor wpisu: batman, dodany: 13.09.2010 21:15, tagi: javascript
Najpopularniejszym serwisem dostarczającym mapy w Internecie jest Google Maps. Nie oznacza to, że konkurencja pogodziła się z porażką na tym polu. Jedną z ciekawszych alternatyw dla Google Maps jest Bing Maps. Oprócz API dostępnego w języku Javascript programiści mogą korzystać z Silverlighta oraz usług sieciowych. Co więcej, programiści PHP również mają możliwość korzystania z map Bing. Gdyby nie jeden drobny szkopuł, Google mogłoby poważnie obawiać się konkurencji ze strony Bing Maps. Niestety mapy w wydaniu Bing nie są zlokalizowane na polski rynek i wyszukanie adresu lub trasy dojazdu graniczy z cudem.
Zanim zaczniemy
Do tworzenia aplikacji opartych o Bing Maps będzie potrzebny nam specjalny klucz. Możemy go zdobyć na stronie www.bingmapsportal.com, do której zalogujemy się korzystając z konta, np Hotmail. Po założeniu konta uzyskujemy możliwość wygenerowania klucza aplikacji, który później będziemy wykorzystywać. Jako ciekawostkę podam, iż konto utworzone w serwisie dla deweloperów Bing Maps daje nam możliwość śledzenia wykorzystania naszych map oraz dodawania własnych aplikacji do map. Ponieważ oba tematy wykraczają daleko poza ramy dzisiejszego wpisu, nie będę się nimi szerzej zajmował.
Podczas tworzenia aplikacji korzystającej z Bing Maps nie musimy od razu rejestrować klucza. Można to zrobić po zakończeniu prac, dzięki czemu statystyki nie będą zawierały testowych odsłon.
Pierwsza mapa
Podobnie jak w przypadku swojego konkurenta, Bing Maps również wymaga zewnętrznego skryptu, z którego będą ładowane klasy. Adresem tym jest
http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.3
gdzie 6.3 oznacza numer wersji, z której chcemy skorzystać.
Kompletny kod, który wyświetli mapę, wygląda następująco.
<html> <head> <title>Pierwsza mapa</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <script type="text/javascript" src=http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.3></script> <script type="text/javascript"> var map = null; function GetMap() { map = new VEMap("mapa"); map.LoadMap(); } </script> </head> <body onload="GetMap();"> <div id="mapa" style="position: relative; width: 600px; height: 400px;"></div> </body> </html>
Uruchomienie powyższego kodu spowoduje wyświetlenie domyślnej mapy o rozmiarze zdefiniowanym w atrybucie style.